该内容是在【博学谷】学习过程中的代码记录,如有任何问题请与作者联系。
也欢迎同在学习鸿蒙开发的小伙伴的留言,一同学习,一同进步。


功能实现(只记录代码,没有相关配置,跑不起来):
图一的代码:
import { router } from '@kit.ArkUI'@Entry
@Component
struct Index {// 计数器ID,保证计数器关闭时一对一的关系@State Id: number = -1// 页面打开时自动运行的代码(生命周期)onPageShow(): void {// 开启计数器this.Id = setInterval(() => {//页面跳转(需要引入router)router.replaceUrl({url: 'pages/SplashPage'})// 关闭计数器clearInterval(this.Id)}, 500)}build() {// 层叠显示Stack() {Image($r('app.media.todoBg')).width('100%').height('100%')Image($r('app.media.todoLog')).width('10%').height('10%')}.width('100%').height('100%')}
}
图二的代码:
import { common } from '@kit.AbilityKit'
import { router } from '@kit.ArkUI';@Entry
@Component
struct SplashPage {// 计数器ID,保证计数器关闭时一对一的关系@State Id: number = -1// 设置倒计时时间@State time: number = 5// 动画移动的距离(偏移量)@State animationOffset: number = -100;// 获得系统参数(用于国际化)getString(name: Resource) {let context = this.getUIContext().getHostContext() as common.UIAbilityContextlet resMgr = context.resourceManagerlet resId = name.id//获取符合当前系统语言地区、颜色模式、分辨率等配置的资源let currentLanguageString = resMgr.getStringSync(resId)return currentLanguageString}build() {Stack() {// 背景图Image($r('app.media.todoBg')).width('100%').height('100%')Column() {Text(`剩余 ${this.time} 秒`).onAppear(() => {// 开启计时器this.Id = setInterval(() => {// 倒计时this.time--// 倒计时结束if (this.time <= 0) {// 页面跳转router.replaceUrl({url: 'pages/LoginPage'})// 关闭计时器clearInterval(this.Id)}}, 1000)})// 控件展示时候调用(生命周期).onClick(() => {// 页面跳转router.replaceUrl({url: 'pages/LoginPage'})// 关闭计时器clearInterval(this.Id)})// 控件点击时调用.width(80).backgroundColor($r('app.color.start_window_background')).fontSize(15).fontColor($r('app.color.text_color_02')).borderRadius(15).padding(8).position({top: 20,right: -100}) //偏移量(不占原位置)Text(this.getString($r('app.string.splash_content1'))).fontSize(30).fontColor($r('app.color.start_window_background')).onAppear(() => {this.animationOffset = 0}).offset({top: 300,left: this.animationOffset})//偏移量(占原位置).animation({duration: 1000, // 动画播放时长iterations: 1 // 动画播放次数})Text(this.getString($r('app.string.splash_content2'))).fontSize(30).fontColor($r('app.color.start_window_background')).onAppear(() => {this.animationOffset = 0}).offset({top: 300,right: this.animationOffset})//偏移量(占原位置).animation({duration: 1000, // 动画播放时长iterations: 1 // 动画播放次数})Text(this.getString($r('app.string.splash_tips'))).fontColor($r('app.color.start_window_background')).fontSize(15).position({bottom: 10})}.height('100%')}.width('100%').height('100%')}
}
图三图四的代码:
import { common } from '@kit.AbilityKit'
import { http } from "@kit.NetworkKit"
import { router } from '@kit.ArkUI'const req = http.createHttp()interface UserResponse {code: numbermessage: stringdata: User
}interface User {id: numberaccount: stringusername: string
}export let userNameID: string = '' // 导出,其它页面需要userNameID@Entry
@Component
struct LoginPage {//注册用办模态@State isShow: boolean = false//登录用,用户名和密码@State username: string = ''@State password: string = ''@State passwordverification: string = ''getString(name: Resource) {let context = this.getUIContext().getHostContext() as common.UIAbilityContextlet resMgr = context.resourceManagerlet resId = name.id//获取符合当前系统语言地区、颜色模式、分辨率等配置的资源let currentLanguageString = resMgr.getStringSync(resId)return currentLanguageString}// 注册用半模态@BuilderRegisterModal() {Stack() {// 背景图Image($r('app.media.LongBack')).opacity(0.3) //透明度Column() {//输入框TextInput({placeholder: '请输入用户名', // 默认提示text: $$this.username // 双向绑定username}).type(InputType.Normal)// 控制输入类型 基础.placeholderColor($r('app.color.start_window_background'))// 默认提示文字颜色.fontColor($r('app.color.start_window_background')).showUnderline(true)// 是否显示下横线.border({width: { bottom: 3 },color: $r('app.color.start_window_background')}).padding(10)//输入框TextInput({placeholder: '请输入密码', // 默认提示text: $$this.password // 双向绑定password}).height(48).backgroundColor(Color.Transparent)// 颜色透明.borderRadius(0).type(InputType.Password)// 控制输入类型 密码.placeholderColor($r('app.color.start_window_background')).fontColor($r('app.color.start_window_background')).border({width: { bottom: 3 },color: $r('app.color.start_window_background')}).padding(10)//输入框TextInput({placeholder: this.getString($r('app.string.repeat_password')),text: $$this.passwordverification}).height(48).backgroundColor(Color.Transparent).borderRadius(0).type(InputType.Password).placeholderColor($r('app.color.start_window_background')).fontColor($r('app.color.start_window_background')).border({width: { bottom: 3 },color: $r('app.color.start_window_background')}).padding(10)Text(this.getString($r('app.string.register_button'))).width('100%').fontSize(25).fontColor($r('app.color.start_window_background')).backgroundColor($r('app.color.primary')).textAlign(TextAlign.Center)// 文字居中.padding(10).margin({top: 50}).borderRadius(50).onClick(async () => {if (this.username.length < 8) {AlertDialog.show({message: '用户名最少8位'})return}if (this.password.length < 6) {AlertDialog.show({message: '密码最少6位'})return}if (this.password == this.passwordverification) {// 发送网络请求const res = await req.request('https://hmajax.itheima.net/api/register', {method: http.RequestMethod.POST,header: {contentType: 'application/json'},extraData: {username: this.username,password: this.password}})const userRes = JSON.parse(res.result.toString()) as UserResponse// 默认不会失败(实际应该判断一下失败,通过返回的code)AlertDialog.show({message: userRes.message})this.isShow = false} else {AlertDialog.show({message: '密码输入不一致,请重新输入'})}})}.height('100%').padding(10).justifyContent(FlexAlign.Start) // 整体从上开始排列}}build() {Stack() {Image($r('app.media.LongBack')).opacity(0.7)Column() {// logoImage($r('app.media.startIcon')).width(50).height(50).borderRadius(25).margin({ top: 50 })Row() {Text(this.getString($r('app.string.splash_content1'))).fontColor($r('app.color.start_window_background')).fontSize(15)Text(' ')Text(this.getString($r('app.string.splash_content2'))).fontColor($r('app.color.start_window_background')).fontSize(15)}.margin({ top: 10 })Text(this.getString($r('app.string.account'))).fontColor($r('app.color.start_window_background')).fontSize(30).margin({ top: 30 })Text(this.getString($r('app.string.account_description'))).fontColor($r('app.color.start_window_background')).fontSize(20)//输入框TextInput({placeholder: '请输入用户名',text: $$this.username}).type(InputType.Normal)// 控制输入类型 基础.placeholderColor($r('app.color.start_window_background'))// 默认提示文字颜色.fontColor($r('app.color.start_window_background')).showUnderline(true)// 是否显示下横线.border({width: { bottom: 3 },color: $r('app.color.start_window_background')}).padding(10).margin({ top: 50, left: 10, right: 10 })TextInput({placeholder: '请输入密码',text: $$this.password}).height(48).backgroundColor(Color.Transparent)// 颜色透明.borderRadius(0).type(InputType.Password)// 控制输入类型 密码.placeholderColor($r('app.color.start_window_background')).fontColor($r('app.color.start_window_background')).border({width: { bottom: 3 },color: $r('app.color.start_window_background')}).padding(10).margin({ left: 10, right: 10 })Text(this.getString($r('app.string.login_button'))).width('100%').fontSize(25).fontColor($r('app.color.start_window_background')).backgroundColor($r('app.color.bg_1')).textAlign(TextAlign.Center).padding(10).margin({ top: 50 }).borderRadius(50).onClick(async () => {// 登录逻辑if (this.username.length < 8) {AlertDialog.show({message: '用户名最少8位'})return}if (this.password.length < 6) {AlertDialog.show({message: '密码最少6位'})return}// 发送网络请求const res = await req.request('https://hmajax.itheima.net/api/login', {method: http.RequestMethod.POST,header: {contentType: 'application/json'},extraData: {username: this.username,password: this.password}})const userRes = JSON.parse(res.result.toString()) as UserResponseif (userRes.code == 10000) {this.isShow = false// 同步导出的数据userNameID = userRes.data.usernamerouter.replaceUrl({url: 'pages/MainPage'})} else {AlertDialog.show({message: userRes.message})}})Text(this.getString($r('app.string.register_button'))).width('100%').fontSize(25).fontColor($r('app.color.start_window_background')).backgroundColor($r('app.color.primary')).textAlign(TextAlign.Center).padding(10).margin({ top: 10 }).borderRadius(50).onClick(() => {this.isShow = true}).bindSheet($$this.isShow, this.RegisterModal(), {height: SheetSize.MEDIUM // 半模态弹出的距离(也就是半模态的大小)}) //半模态Row() {Text(this.getString($r('app.string.privacy_statement'))).fontColor($r('app.color.start_window_background')).fontSize(15)Text(' ') // 用空格来代替中间的间距(方法不唯一:justifyContent也能实现)Text(this.getString($r('app.string.verification_code_login'))).fontColor($r('app.color.start_window_background')).fontSize(15)}.width('100%').justifyContent(FlexAlign.Center).position({bottom: 50})}.height('100%')}.width('100%').height('100%')}
}
图五图六图七的代码:
import { userNameID } from './LoginPage'
import { router } from '@kit.ArkUI'
import { http } from "@kit.NetworkKit"
import { JSON } from '@kit.ArkTS'const req = http.createHttp()// 我的页面使用
interface UserResponse {message: stringdata: User
}interface User {avatar: stringemail: stringnickname: stringgender: numberdesc: string
}// 知道页面使用
interface DatumResponse {message: stringdata: Datum[]
}interface Datum {cmtcount: number; //新闻评论总数id: number; //新闻idimg: string; //新闻图片地址source: string; //新闻来源time: string; //新闻发布时间title: string; //新闻标题
}// 去做页面使用
interface Thing {time: numberthing: stringisSelected: boolean
}// 数据持久化
let things: Thing[] = []
PersistentStorage.persistProp('things', things)// 数据按时间分组
function classifyByDate(things: Thing[]) {return things.reduce((acc, thing) => {const formattedDate =`${new Date(thing.time).toISOString().split("T")[0]} ${new Date(thing.time).toTimeString().split(":")[0]}:${new Date(thing.time).toTimeString().split(":")[1]}`if (!acc[formattedDate]) {acc[formattedDate] = []}acc[formattedDate].push(thing)return acc}, {} as Record<string, Thing[]>)
}// 修正数据格式用于第二层循环
function formatTheData(time: string, thingTemp: Thing[]) {const thingList: Thing[] = Object.values(classifyByDate(thingTemp)[time]).flat()return thingList
}@Entry
@Component
struct MainPage {// 读取持久化的数据@StorageLink('things')things: Thing[] = []// 待做事件列表同步是否勾选列表(@State实时控制页面展示)@State isSelected: boolean[] = []// 待做事件个数统计,用于我的页面展示@State agentNumber: number = 0// 具体事件@State thingString: string = ''@State user: User = {avatar: '',email: '',nickname: '',gender: 0,desc: ''}@State datums: Datum[] = [{cmtcount: 0, //新闻评论总数id: 0, //新闻idimg: '', //新闻图片地址source: '', //新闻来源time: '', //新闻发布时间title: ''//新闻标题}]// 页面构建前初始化aboutToAppear() {// 获取持久化数据,同步,勾选状态和待做事件个数this.isSelected = this.things.map(thing => thing.isSelected)this.agentNumber = this.things.filter(thing => !thing.isSelected).length}@BuilderListItemGroupHeader(time: string) {Column() {Text(time).fontSize(20).fontColor($r('app.color.text_primary')).backgroundColor($r('app.color.primary')).width('100%').padding(10)}}@BuilderDeleteButton(item: Thing) {Button('删除').width(100).type(ButtonType.Normal).fontColor($r('app.color.start_window_background')).backgroundColor($r('app.color.primary')).onClick(() => {const index = this.things.findIndex(thing => thing.time === item.time)if (index > -1) {this.things.splice(index, 1)this.isSelected.splice(index, 1)}this.agentNumber = this.things.filter(thing => !thing.isSelected).length// AlertDialog.show({// title: '事件详情',// message: this.events.reduce((acc, item, index) => {// return acc +// `#${index + 1}\n` +// `名称: ${item.event}\n` +// `数据: ${item.data}\n` +// `状态: ${item.isSelected ? '已选中' : '未选中'}\n\n`;// }, '')// })})}// 去做@BuilderquzuoBuilder() {Scroll() {Column() {Text('去做吧').fontSize(30).fontColor($r('app.color.primary'))Row({ space: 10 }) {TextArea({text: this.thingString,placeholder: '待做...',}).width(230).height(50).fontSize(16).fontColor($r('app.color.start_window_background')).backgroundColor($r('app.color.primary')).placeholderFont({ size: 16, weight: 400 }).placeholderColor($r('app.color.start_window_background')).borderRadius(15).onChange((value: string) => {this.thingString = value;})Text('提交').width(100).height(50).fontSize(16).borderRadius(15).fontColor($r('app.color.start_window_background')).backgroundColor($r('app.color.primary')).textAlign(TextAlign.Center).onClick(() => {// 添加一个带当前时间戳的对象const newThing: Thing = {time: Date.now(),thing: this.thingString,isSelected: false}this.things.push(newThing);this.isSelected.push(newThing.isSelected);this.agentNumber = this.things.filter(event => !event.isSelected).length;})}.margin({ top: 10 })Column() {List({ space: 10 }) {ForEach(Object.keys(classifyByDate(this.things)), (time: string) => {ListItemGroup({header: this.ListItemGroupHeader(time)}) {ForEach(formatTheData(time, this.things), (thingItem: Thing) => {ListItem() {Row() {Checkbox({ group: 'checkboxGroup' }).select(thingItem.isSelected).selectedColor($r('app.color.primary')).shape(CheckBoxShape.ROUNDED_SQUARE).onChange((value: boolean) => {const index = this.things.findIndex(thing => thing.time === thingItem.time);if (index !== -1) {// 安全复制 isSelected 数组const newIsSelected = this.isSelected.slice();newIsSelected[index] = value;// 安全复制 events 数组,更新 isSelected 字段const newThings = this.things.map((thing, i): Thing => ({time: thing.time,thing: thing.thing,isSelected: newIsSelected[i]}));this.things = newThings;this.isSelected = newIsSelected;this.agentNumber = newThings.filter(event => !event.isSelected).length;}})Text(thingItem.thing).width('100%').fontSize(20).fontColor(this.isSelected[this.things.findIndex(item => item.time === thingItem.time)] ?$r('app.color.text_color_03') : $r('app.color.primary')).decoration({type: this.isSelected[this.things.findIndex(item => item.time === thingItem.time)] ?TextDecorationType.LineThrough : TextDecorationType.None,color: $r('app.color.text_color_03')})}.padding(10)}.transition({ type: TransitionType.Delete, opacity: 0 }).swipeAction({end: {builder: () => {this.DeleteButton(thingItem)},actionAreaDistance: 56,}})})}})}}.padding(10)}.justifyContent(FlexAlign.Start)}.height('100%').align(Alignment.TopStart)}// 知道@BuilderzhidaoBuilder() {Scroll() {Column({ space: 15 }) {ForEach(this.datums, (datum: Datum) => {Row() {Column() {Text(datum.title).width(200).fontSize(25).textOverflow({ overflow: TextOverflow.Ellipsis })// 文字溢出.maxLines(2) // 最大行数Row() {Row() {Text(datum.source).width(50).fontSize(15).textOverflow({ overflow: TextOverflow.Ellipsis })// 文字溢出.maxLines(1) // 最大行数Text('|').width(3).fontSize(15)Text(datum.cmtcount.toString()).width(30).fontSize(15)}Text(datum.time).width(80).fontSize(15).textOverflow({ overflow: TextOverflow.Ellipsis })// 文字溢出.maxLines(1) // 最大行数}.width(200).justifyContent(FlexAlign.SpaceBetween)}.height(100).justifyContent(FlexAlign.SpaceBetween)Image(datum.img).width(100).height(100)}.width('100%').height(100).justifyContent(FlexAlign.SpaceBetween).padding(20)})}}.width('100%').height('100%')}// 我的@BuilderwodeBuilder() {Stack() {Image($r('app.media.LongBack')).opacity(0.7)Column({ space: 10 }) {Column() {Image(this.user.avatar).width(40).height(40).offset({ top: -30 })Text(this.user.nickname)Text(this.user.email)Text(`还有${this.agentNumber}条代办事项`)}.width('90%').height(200).backgroundColor($r('app.color.start_window_background')).opacity(0.7).alignItems(HorizontalAlign.Center).borderRadius(30).justifyContent(FlexAlign.SpaceAround).margin({ top: 50 })Column() {Row() {Text('用户昵称')Text(this.user.nickname)}.width('90%').justifyContent(FlexAlign.SpaceBetween)Text().width('90%').height(1).backgroundColor($r('app.color.primary'))Row() {Text('用户性别')Text(this.user.gender == 0 ? '男' : '女')}.width('90%').justifyContent(FlexAlign.SpaceBetween)Text().width('90%').height(1).backgroundColor($r('app.color.primary'))Row() {Text('用户简介')Text(this.user.desc)}.width('90%').justifyContent(FlexAlign.SpaceBetween)}.width('90%').height(150).backgroundColor($r('app.color.start_window_background')).opacity(0.7).alignItems(HorizontalAlign.Center).borderRadius(30).justifyContent(FlexAlign.SpaceAround).padding(10)Text('修改用户信息').width('90%').height(50).backgroundColor($r('app.color.start_window_background')).opacity(0.7).borderRadius(30).textAlign(TextAlign.Center).onClick(() => {// 添加跳转逻辑router.pushUrl({url: 'pages/UserPage',})})Text('退出登录').width('90%').height(50).backgroundColor($r('app.color.start_window_background')).opacity(0.7).borderRadius(30).textAlign(TextAlign.Center).onClick(() => {// 添加跳转逻辑router.replaceUrl({url: 'pages/SplashPage',})})}.width('100%').height('100%')}}async getUser() {const res = await req.request('https://hmajax.itheima.net/api/settings?creator=' + userNameID)const userRes = JSON.parse(res.result.toString()) as UserResponsethis.user = userRes.data}async getDatums() {const res = await req.request('https://hmajax.itheima.net/api/news')const datumRes = JSON.parse(res.result.toString()) as DatumResponsethis.datums = datumRes.data}onPageShow(): void {this.getDatums()this.getUser()}@BuildertabTitleBuilder(url: string, text: string) {Column() {Image($r(url)).width(40)Text(text).fontColor($r('app.color.primary'))}}build() {Tabs() {TabContent() {this.quzuoBuilder()}.tabBar(this.tabTitleBuilder('app.media.go', '去做'))TabContent() {this.zhidaoBuilder()}.tabBar(this.tabTitleBuilder('app.media.zhidao', '知道'))TabContent() {this.wodeBuilder()}.tabBar(this.tabTitleBuilder('app.media.wode', '我的'))}.barPosition(BarPosition.End).barBackgroundColor(Color.White).barHeight(80).divider({ strokeWidth: 2 })}
}
图八的代码:
import { userNameID } from './LoginPage'
import { http } from "@kit.NetworkKit"
import { router } from '@kit.ArkUI'const req = http.createHttp()interface UserResponse {message: stringdata: User
}interface User {avatar: stringemail: stringnickname: stringgender: numberdesc: string
}@Entry
@Component
struct UserPage {@State userAvatar: string = ''@State userEmail: string = ''@State userName: string = ''@State userGender: number = 0@State userGenderString: string = ''@State userDesc: string = ''async onPageShow() {const res = await req.request('https://hmajax.itheima.net/api/settings?creator=' + userNameID) // userName唯一标识const userRes = JSON.parse(res.result.toString()) as UserResponsethis.userAvatar = userRes.data.avatarthis.userEmail = userRes.data.emailthis.userName = userRes.data.nicknamethis.userGender = userRes.data.genderthis.userGenderString = this.userGender == 0 ? "男" : '女'this.userDesc = userRes.data.desc}build() {Column() {Image($r('app.media.fanhuijiantou')).width(20)// 通过宽度自动修正高度.position({ left: 10 }).onClick(() => {// 返回上一页router.back()})// 头像Image(this.userAvatar).width(50).height(50).margin({ top: 100 })Row({ space: 10 }) {Text('用户昵称:').fontSize(20)TextInput({placeholder: this.userName,text: $$this.userName}).width(200).placeholderColor($r('app.color.base_blake')).fontColor($r('app.color.base_blake')).border({width: { bottom: 1 },color: $r('app.color.base_blake')}).showUnderline(true).padding(0)}.width('90%').margin({ top: 30 })Row({ space: 10 }) {Text('用户性别:').fontSize(20)Select([{ value: '男' },{ value: '女' }]).width(200).font({ size: 16, weight: 500 })// 设置字体大小和粗细.fontColor($r('app.color.base_blake')).backgroundColor($r('app.color.bg_primary')).value(this.userGenderString)// 选中的展示的内容.selected(this.userGender)// 下拉选择列表中选中的内容(从0开始).selectedOptionFont({ size: 16, weight: 500 })// 设置选中的字体大小和粗细.optionFont({ size: 16, weight: 500 })// 设置未选中的字体大小和粗细.optionWidth(200)// 设置下拉选项的宽度.optionHeight(300)// 设置下拉选项的高度(支持滑动).menuAlign(MenuAlignType.START, { dx: 0, dy: 0 })// 设置展示框和下拉框的位置关系(居左/居中/居右)和 偏移量.onSelect((index: number, text?: string | undefined) => {this.userGender = index;if (text) {this.userGenderString = text;}})}.width('90%').margin({ top: 30 })Text('用户简介:').fontSize(20).width('90%').margin({ top: 30 })TextArea({text: this.userDesc}).fontSize(16).fontColor($r('app.color.base_blake')).backgroundColor($r('app.color.bg_primary')).placeholderFont({ size: 16, weight: 400 }).width('90%').height(100).margin(10).onChange((value: string) => {this.userDesc = value;}) //数据实时反馈Text('确定修改').width('90%').fontSize(25).fontColor($r('app.color.start_window_background')).backgroundColor($r('app.color.primary')).textAlign(TextAlign.Center).padding(10).borderRadius(50).onClick(async () => {// 1. 非空判断if (this.userName == '' || this.userDesc == '') {AlertDialog.show({message: '信息不能为空,请检查哦~ ღ( ´・ᴗ・` )比心'})return}const res = await req.request(`https://hmajax.itheima.net/api/settings`, {method: http.RequestMethod.PUT,header: {contentType: 'application/json'},extraData: {creator: userNameID,email: this.userEmail,nickname: this.userName,gender: this.userGender,desc: this.userDesc}})const addRes = JSON.parse(res.result.toString()) as UserResponseAlertDialog.show({message: addRes.message})router.back()}).margin({ top: 10 })}.width('100%').height('100%')}
}