『江鸟中原』鸿蒙——待办清单

打印 上一主题 下一主题

主题 982|帖子 982|积分 2946

 
先容

 
本应用基于Stage模型下的UIAbility开发,《待办清单》是一款使命管理应用!应用界面简单直观,让您可以轻松地保持组织和使命的把控。无论是管理工作项目、家庭琐事还是个人目的,我们的应用都能满足您的需求,让您可以轻松跟踪使命并保持高效。
环境搭建

我们起首必要完成HarmonyOS开发环境搭建,可参照如下步骤进行。
软件要求



  • DevEco Studio版本:DevEco Studio 3.1 Release。
  • HarmonyOS SDK版本:API version 9。
硬件要求



  • 设备类型:华为手机或运行在DevEco Studio上的华为手机设备模仿器。
  • HarmonyOS体系:3.1.0 Developer Release。
环境搭建


  • 安装DevEco Studio,详情请参考下载和安装软件。
  • 设置DevEco Studio开发环境,DevEco Studio开发环境必要依赖于网络环境,必要连接上网络才能确保工具的正常使用,可以根据如下两种情况来配置开发环境:

    • 假如可以直接访问Internet,只需进行下载HarmonyOS SDK操纵。
    • 假如网络不能直接访问Internet,必要通过署理服务器才可以访问,请参考配置开发环境。

  • 开发者可以参考以下链接,完成设备调试的相干配置:

    • 使用真机进行调试
    • 使用模仿器进行调试

项目结构


项目展示

《待办清单》APP展示

进入主页后点击“+”号按钮即可跳转到新增使命,在新增使命页中输入使命,点击确定后跳转到首页,即可发现使命已经添加上了
   
  但完成使命后,可以点击使命左边的复选框,即完成该使命。可以通过上方的按钮跳转,对使命进行了筛选,能更好管理使命
   
  假如此使命输入有误或其他缘故原由想要删除此使命,可以直接点击该使命右方的删除按钮,点击之后会弹出弹窗,防止用户误触。之后点击是,即可完成对使命的删除
   
  别的,该APP还有将数据保存到手机本地的功能,清理掉手机应用后台之后,再打开会发现,原来输入的数据仍保存到应用之中,可以供用户循环使用。
   

  
 

至此,《待办清单》APP所有功能展示完毕,接下来开始对源代码进行剖析
项目剖析

首页 Index

此页是整个应用的入口组件,用于管理使命列表和控制页面的显示。
它包含了一些状态变量和方法,通过调用TaskHelper提供的方法来读取和保存使命列表数据,并根据displayAddPage状态变量的值来控制页面的显示。
  1.  @State displayAddPage: boolean = false
  2.  @State @Watch('saveTaskList') taskList: Array<TaskModel> = []
复制代码
名为Index的组件,是整个应用的入口组件。它包含了一些状态变量和方法,用于管理使命列表和控制页面的显示。在build()函数中,根据displayAddPage状态变量的值来判定当前应该显示AddPage还是ListPage组件。
跳转到AddTask和ListPage
  1. @State displayAddPage: boolean = false
  2. build() {
  3.    if (this.displayAddPage) {
  4.      AddPage({ displayAddPage: $displayAddPage,
  5.        taskList: $taskList })
  6.    } else {
  7.      ListPage({ displayAddPage: $displayAddPage,
  8.        taskList: $taskList })
  9.    }
  10.   }
复制代码
在aboutToAppear()函数中,调用了TaskHelper.readTaskList()方法来读取本地存储的使命列表数据,并将其赋值给taskList状态变量。在saveTaskList()函数中,调用了TaskHelper.saveTaskList()方法来将当前的使命列表数据保存到本地存储中。
  1. @State @Watch('saveTaskList') taskList: Array<TaskModel> = []
  2. saveTaskList() {
  3.    TaskHelper.saveTaskList(this.taskList)
  4. }
  5. aboutToAppear() {
  6.    this.taskList = TaskHelper.readTaskList()
  7. }
复制代码
新增使命页 AddTask

此页重要展示了新增使命页的界面,并通过用户的输入,将输入内容保存。是一个待办清单应用中用于添加新使命的页面。
它包含了一个Boolean类型的状态变量displayAddPage,用于控制页面的显示与隐藏。此外,还有一个用于存储输入的使命内容的字符串类型状态变量taskContent,以及一个数组类型状态变量taskList,用于存储使命列表。
  1. @Link displayAddPage: boolean
  2.  @State taskContent: string = ''
  3.  @Link taskList: [TaskModel]
复制代码
在页面的构建函数build()中,使用了一些框架提供的组件和样式属性,例如Column、Stack、Image、Text、TextArea、Button等,用于构建页面的各个元素。在确定按钮的onClick变乱中,使用了体系提供的getCurrentTime()方法获取当前时间,然后创建了一个新的TaskModel对象,并将其添加到taskList数组中。最后,将displayAddPage设置为false,隐藏该页面。
  1. build() {
  2.    Column({ space: 20 }) {
  3.        Stack() {
  4.            Column() {
  5.                Image($r('app.media.icon_back'))
  6.                    .width(30)
  7.                    .onClick(() => {
  8.                    this.displayAddPage = false
  9.                })
  10.            }
  11.            .width('100%')
  12.                .alignItems(HorizontalAlign.Start)
  13.            Text('新增任务')
  14.                .fontSize(20)
  15.                .fontWeight(FontWeight.Bold)
  16.        }
  17.        TextArea({ text: this.taskContent, placeholder: '请输入任务内容' })
  18.            .backgroundColor(Color.White)
  19.            .width(315)
  20.            .height(201)
  21.            .borderRadius(9)
  22.            .borderColor(0xC2BFBF)
  23.            .onChange((value) => {
  24.            this.taskContent = value
  25.        })
  26.        Button({ stateEffect: true,
  27.                type: ButtonType.Normal }) {
  28.            Text('确定')
  29.                .fontColor(Color.White)
  30.        }
  31.        .width(315)
  32.            .height(50)
  33.            .borderRadius(5)
  34.            .onClick(() => {
  35.            systemDateTime.getCurrentTime(true).then((currentTime) => {
  36.                // @ts-ignore
  37.                let task = new TaskModel({
  38.                    taskId: currentTime,
  39.                    taskContent: this.taskContent,
  40.                    isCompleted: false
  41.                })
  42.                // this.taskList.push(task)
  43.                this.taskList.splice(0, 0, task)
  44.                this.displayAddPage = false
  45.            })
  46.        })
  47.    }
  48.    .width('100%')
  49.        .height('100%')
  50.        .backgroundColor(0xBED0DC)
  51.        .padding({ top: 50, left: 20, bottom: 20, right: 20 })
  52. }
复制代码
使命展示页 listPage

此页面实现最重要的功能,是一个用于展示使命列表和管理使命的页面组件,包括了使命筛选、使命展示和使命操纵等功能。
是用于展示使命列表和管理使命的页面。它包含了一些状态变量和方法,用于获取使命列表、删除使命等操纵。
  1.  @Link displayAddPage: boolean
  2.  @Link taskList: Array<TaskModel>
  3.  @State taskType: string = 'all'
复制代码
在build()函数中,使用了一些前端框架提供的组件和样式属性,例如Column、Text、Row、Radio、Stack、Image、List、ListItem、Checkbox、Button等,用于构建页面的各个元素。
复选框的调用函数
  1. deleteTask(taskId: number) {
  2.    AlertDialog.show({
  3.      title: '删除',
  4.      message: '你确定要删除吗?',
  5.      autoCancel: true,
  6.      alignment: DialogAlignment.Bottom,
  7.      offset: { dx: 0, dy: -20 },
  8.      primaryButton: {
  9.        value: '否',
  10.        action: () => {
  11.        }
  12.      },
  13.      secondaryButton: {
  14.        value: '是',
  15.        action: () => {
  16.          // 具体执行动作的地方
  17.          let taskIndex = TaskHelper.getIndexByTaskId(this.taskList, taskId)
  18.          this.taskList.splice(taskIndex, 1)
  19.        }
  20.      }
  21.    }
  22.    )
  23.   }
复制代码
获取使命列表的调用函数
  1. getTaskList(): Array<TaskModel> {
  2.    if (this.taskType == 'all') {
  3.      return this.taskList
  4.    } else if (this.taskType == 'todo') {
  5.      return this.taskList.filter((item) => {
  6.        if (!item.isCompleted) {
  7.          return true
  8.        }
  9.      })
  10.    } else if (this.taskType == 'finish') {
  11.      return this.taskList.filter((item) => {
  12.        if (item.isCompleted) {
  13.          return true
  14.        }
  15.      })
  16.    }
  17.   }
复制代码
在页面中,有一个用于显示使命类型(全部、待办、完成)的Radio按钮组,用户可以选择不同的类型来筛选使命。
  1. Text('我的任务')
  2.    .fontSize(20)
  3.    .fontWeight(FontWeight.Bold)
  4. Row() {
  5.    Column() {
  6.        Text('全部')
  7.        Radio({ value: 'all', group: 'taskType' })
  8.            .onChange((isSelect) => {
  9.            if (isSelect) {
  10.                this.taskType = 'all'
  11.            }
  12.        })
  13.            .checked(this.taskType == 'all' ? true : false)
  14.    }
  15.    Column() {
  16.        Text('待办')
  17.        Radio({ value: 'todo', group: 'taskType' })
  18.            .onChange((isSelect) => {
  19.            if (isSelect) {
  20.                this.taskType = 'todo'
  21.            }
  22.        })
  23.            .checked(this.taskType == 'todo' ? true : false)
  24.    }
  25.    Column() {
  26.        Text('完成')
  27.        Radio({ value: 'finish', group: 'taskType' })
  28.            .onChange((isSelect) => {
  29.            if (isSelect) {
  30.                this.taskType = 'finish'
  31.            }
  32.        })
  33.            .checked(this.taskType == 'finish' ? true : false)
  34.    }
  35. }
  36. .width('100%')
  37. .justifyContent(FlexAlign.SpaceAround)
复制代码
使命列表部门使用了List和ListItem组件来展示使命,每个使命包含复选框、使命内容和删除按钮,用户可以勾选复选框标记使命完成,也可以点击删除按钮删除使命。
  1. Stack() {
  2.    Image($r('app.media.bg'))
  3.        .width(338)
  4.        .height(500)
  5.    Column({ space: 10 }) {
  6.        List() {
  7.            ForEach(this.getTaskList(), (item: TaskModel, index) => {
  8.                ListItem() {
  9.                    Row() {
  10.                        Checkbox()
  11.                            .select(item.isCompleted)
  12.                            .onChange((value) => {
  13.                            let taskIndex = TaskHelper.getIndexByTaskId(this.taskList, item.taskId)
  14.                            let oldTask = this.taskList[taskIndex]
  15.                            let newTask = new TaskModel({
  16.                                taskId: item.taskId,
  17.                                taskContent: oldTask.taskContent,
  18.                                isCompleted: value })
  19.                            this.taskList[taskIndex] = newTask
  20.                        })
  21.                        Text(item.taskContent)
  22.                            .margin({ left: 10 })
  23.                            .decoration({ type: item.isCompleted ? TextDecorationType.LineThrough : TextDecorationType.None })
  24.                            .width('70%')
  25.                            .maxLines(1)
  26.                            .textOverflow({ overflow: TextOverflow.Ellipsis })
  27.                        Blank()
  28.                        Image($r('app.media.icon_delete'))
  29.                            .width(20)
  30.                            .onClick(() => {
  31.                            this.deleteTask(item.taskId)
  32.                        })
  33.                    }
  34.                    .width('100%')
  35.                }
  36.            })
  37.        }
  38.        .width('70%')
  39.            .height(400)
  40.    }
  41.    .margin({ top: 70 })
  42. }
  43. .alignContent(Alignment.Top)
复制代码
此外,页面底部还有一个用于添加新使命的按钮。
  1. Column() {
  2.    Button({ type: ButtonType.Circle,
  3.            stateEffect: true }) {
  4.        Text('+')
  5.            .fontSize(50)
  6.            .fontColor(Color.White)
  7.    }
  8.    .width(60)
  9.        .height(60)
  10.        .onClick(() => {
  11.        this.displayAddPage = true
  12.    })
  13. }
  14. .width('100%')
  15.    .alignItems(HorizontalAlign.End)
复制代码
使命模型类 TaskModel

这是一个名为TaskModel的类,它体现一个使命模型。该类具有三个属性:taskId(使命ID)、taskContent(使命内容)和isCompleted(使命是否已完成)。它还包含一个构造函数,用于初始化这些属性。
构造函数接受一个对象作为参数,对象包含了taskId、taskContent和isCompleted这三个属性的值。在构造函数中,使用传入的对象来初始化类的属性。
这个类的作用是体现一个使命的数据模型,包含了使命的ID、内容和完成状态等信息。在实际应用中,可以使用这个类来创建和管理使命对象的数据。
  1. export class TaskModel {
  2.  taskId: number = 0
  3.  taskContent: string = ''
  4.  isCompleted: boolean = false
  5.  constructor({taskId: taskId, taskContent: taskContent, isCompleted: isCompleted}) {
  6.    this.taskId = taskId
  7.    this.taskContent = taskContent
  8.    this.isCompleted = isCompleted
  9.   }
  10. }
复制代码
文件保存工具类 FileHelper

这段代码是一个名为FileHelper的类,用于处置处罚文件读写操纵。它包含了两个静态方法:saveJsonData和readJsonData。
saveJsonData方法用于将JSON数据保存到文件中。它接受两个参数:jsonObj体现要保存的JSON对象,fileName体现要保存的文件名。在方法内部,它使用@ohos.file.fs模块来获取应用文件路径,并根据文件路径新建并打开文件。然后将JSON对象转换为字符串,并写入文件中。
readJsonData方法用于从文件中读取JSON数据。它接受一个参数fileName,体现要读取的文件名。在方法内部,它同样使用@ohos.file.fs模块来获取应用文件路径,并读取文件中的文本内容。然后将读取到的文本内容转换为JSON对象并返回。
这个FileHelper类提供了方便的方法来保存和读取JSON数据,可以在应用中用于处置处罚文件读写操纵。
  1. export class FileHelper {
  2.  // 保存json数据
  3.  static saveJsonData(jsonObj: any, fileName: string) {
  4.    // 获取应用文件路径
  5.    let context = getContext(this) as common.UIAbilityContext
  6.    let filesDir = context.filesDir
  7.    let filePath = `${filesDir}/${fileName}`
  8.    // 新建并打开文件
  9.    try {
  10.      let file = fs.openSync(filePath, fs.OpenMode.WRITE_ONLY | fs.OpenMode.TRUNC | fs.OpenMode.CREATE);
  11.      let jsonStr = JSON.stringify(jsonObj)
  12.      console.log(jsonStr)
  13.      fs.writeSync(file.fd, jsonStr)
  14.      fs.closeSync(file)
  15.    } catch (e) {
  16.      console.log(`write file error ${e}`)
  17.    }
  18.   }
  19.  // 读取json数据
  20.  static readJsonData(fileName: string):any {
  21.    // 获取应用文件路径
  22.    let context = getContext(this) as common.UIAbilityContext
  23.    let filesDir = context.filesDir
  24.    let filePath = `${filesDir}/${fileName}`
  25.    var userStr = ""
  26.    try {
  27.      userStr = fs.readTextSync(filePath)
  28.    } catch (e) {
  29.      console.log(`read file error ${e}`)
  30.    }
  31.    if (userStr.length > 0) {
  32.      console.log(userStr)
  33.      return JSON.parse(userStr)
  34.    }
  35.    return {}
  36.   }
  37. }
复制代码
工具调用类 TaskHelper

这是一个名为TaskHelper的类,用于处置处罚使命列表数据的读取和保存。它包含了三个静态方法:getIndexByTaskId、saveTaskList和readTaskList。
getIndexByTaskId方法用于根据使命ID在使命列表中查找对应的索引位置。它接受两个参数:taskList体现使命列表数组,taskId体现要查找的使命ID。在方法内部,它遍历使命列表,查找匹配的使命ID,并返回对应的索引位置。假如找不到匹配的使命ID,就返回-1。
saveTaskList方法用于将使命列表数据保存到文件中。它接受一个参数taskList,体现要保存的使命列表数组。在方法内部,它调用FileHelper的saveJsonData方法,将使命列表数据保存到名为'task.data'的文件中。
readTaskList方法用于从文件中读取使命列表数据。它调用FileHelper的readJsonData方法来读取名为'task.data'的文件中的数据,并将读取到的JSON数据转换为TaskModel对象的数组。
这个TaskHelper类提供了方便的方法来处置处罚使命列表数据的读取和保存,可以在应用中用于管理使命列表的数据。
  1. export class TaskHelper {
  2.  static getIndexByTaskId(taskList: Array<TaskModel>, taskId: number) {
  3.    for (let i = 0; i < taskList.length; i++) {
  4.      // @ts-ignore
  5.      if (taskList[i].taskId == taskId) {
  6.        return i
  7.      }
  8.    }
  9.    return -1
  10.   }
  11.  static saveTaskList(taskList: Array<TaskModel>) {
  12.    FileHelper.saveJsonData(taskList, 'task.data')
  13.   }
  14.  static readTaskList(): Array<TaskModel> {
  15.    let jsonData = FileHelper.readJsonData('task.data')
  16.    let taskList: Array<TaskModel> = []
  17.    Object.assign(taskList, jsonData)
  18.    return taskList
  19.   }
  20. }
复制代码
总结 

开发待办清单APP必要计划良好的UI界面、实现完满的业务逻辑和数据模型、实现本地存储和测试优化等,才能开发出高质量的APP并吸引更多用户使用。
 

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

渣渣兔

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表