HarmonyOS Next 实现登录注册页面(ARKTS) 并使用Springboot作为后端提供接口

1. HarmonyOS next

ArkTS

ArkTS围绕应用开发在 TypeScript (简称TS)生态基础上做了进一步扩展,继承了TS的所有特性,是TS的超集

ArkTS在TS的基础上扩展了struct和很多的装饰器以达到描述UI和状态管理的目的

以下代码是一个基于 HarmonyOS 的登录页面组件的示例代码,主要实现了用户登录功能以及一些数据存储和页面跳转的操作。下面我会逐步解释每个部分并添加注释:

2. 实例

3. 功能分区

1.1.HTTP获取后台接口数据,以下是示例
复制代码
  async jwt(jwt: string) {
    try {
      const res = await this.httpUtil.request(`192.168.xxx.xxx/readers/userinfo`, {
        method: http.RequestMethod.GET,
        extraData: { no: jwt },
      });
      let data = JSON.parse(res.result.toString());
      return data;
    } catch (error) {
      throw error;
    }
  }
1.2 接口数据(作为测试,可以直接使用json):
2.生命周期函数的使用--AboutToAppear AboutToDisappear
复制代码
  aboutToAppear() {
    let httpRequest = http.createHttp()
    this.httpUtil = httpRequest
    // todo 初始化上一次访问时间
    this.getPreTime()
    // todo 初始化当前时间
    this.getLocalTimeToPreference()
    // todo 初始化本地数据库的密码和用户名
    this.getUserInfo()
  }
3.APPStorage进程作为缓存,只能在应用运行时使用
4.DATAPreference 数据持久化,存于用户本机
4. 分层结构

4.代码演示

  1. 导入模块:

    import router from '@ohos.router' // 导入路由模块
    import storage from '@ohos.data.storage' // 导入数据存储模块
    import App from '@system.app' // 导入应用模块
    import Prompt from '@system.prompt' // 导入提示模块
    import http from '@ohos.net.http' // 导入网络请求模块
    import { RouterInfo } from '../../Pojo/RouterInfo' // 导入自定义的 RouterInfo 类
    import common from '@ohos.app.ability.common' // 导入通用模块
    import dataPreference from '@ohos.data.preferences' // 导入数据首选项模块

  2. 定义 `Login` 结构体:

    @Entry
    @Component
    struct Login {
    ? // 定义状态变量
    ? @State username: string = ""
    ? @State pwd: string = ""
    ? @State allow: boolean = false
    ? @State upload: boolean = true
    ? @State uploadTag: boolean = false
    ? @State lastLocalTime: string = ""
    ??
    ? // 其他属性和方法...
    }

  3. 实例化 `RouterInfo` 对象和初始化方法:

RouterInfo是一个自定义的类

复制代码
export class RouterInfo{
  name:string
  url:string
  message:string

  constructor(name,url,message) {
    this.name=name
    this.url=url
    this.message=message
  }
}

Router = new RouterInfo("进入主页", "pages/Books/Main", "主页面")

aboutToAppear() {
? // 初始化操作,包括创建 HTTP 请求对象、获取上次访问时间、初始化本地时间等
}
  1. 页面跳转方法 `goTo()`:

    goTo(Router: RouterInfo) {
    ? // 调用路由模块进行页面跳转
    }

  2. 异步获取用户信息的方法 `jwt()`:

    async jwt(jwt: string) {
    ? // 发起网络请求获取用户信息
    }

  3. 存储当前时间到用户首选项方法 `getLocalTimeToPreference()`:

    // 获取当前时间并存入用户首选项
    getLocalTimeToPreference(){
    const currentDate: Date = new Date();
    const currentYear: number = currentDate.getFullYear();
    const currentMonth: number = currentDate.getMonth() + 1; // 注意:月份从 0 开始,需要加 1
    const currentDay: number = currentDate.getDate();
    const currentHour: number = currentDate.getHours();
    const currentMinute: number = currentDate.getMinutes();
    const currentSecond: number = currentDate.getSeconds();

    复制代码
     const curTime = `北京时间:${currentYear}-${currentMonth}-${currentDay} ${currentHour}:${currentMinute}:${currentSecond}`;
    
     dataPreference.getPreferences(this.context, "myBookStore").then(preferences => {
       preferences.put("curTime", curTime).then(_ => {
         preferences.flush();
       });
     }).catch((err: Error) => {
       console.error(err.message);
     });

    }

  4. 获取上一次访问时间方法 `getPreTime()` 和关闭应用更新时间方法

    // 获取上一次的时间--lastTime
    getPreTime(){
    dataPreference.getPreferences(this.context, "myBookStore").then(preferences => {
    if (!preferences.has("lastTime")) {
    console.log("数据并未能保存");
    } else {
    preferences.get("lastTime", 'null').then((value) => {
    this.last=value.toLocaleString()
    // AlertDialog.show({message:上一次访问时间:${this.last}})
    console.log("数据为:" + value);
    }).catch(_ => {
    console.log("读取失败");
    });
    }
    });
    }

    // 关闭应用时将lastTime置换为curTime,并将curTime替换为空值
    closeAppAndUpdateTime(){
    dataPreference.getPreferences(this.context, "myBookStore").then(preferences => {
    preferences.get("curTime", '').then((curTime) => {
    preferences.put("lastTime", curTime);
    preferences.put("curTime", '');
    preferences.flush();
    console.log("上一次时间已更新,当前时间已清空");
    }).catch((err: Error) => {
    console.error(err.message)
    });
    }).catch((err: Error) => {
    console.error(err.message);
    });
    }

  5. 用户登录方法 `login()` 和相关辅助方法:

    login() {
    ? // 用户登录逻辑,包括密码验证、令牌解析、存储用户信息等操作
    }

    uploadUserInfo() {
    ? // 将用户信息上传到本地存储
    }

    getUserInfo() {
    ? // 获取本地存储的用户信息
    }

  6. 构建页面布局的方法 `build()`:

    build() {
    ? // 构建页面布局,包括输入框、按钮、复选框等组件
    }

这段代码实现了一个简单的登录页面,涵盖了用户输入、网络请求、数据存储等功能,并且使用 HarmonyOS 的一些模块来实现这些功能。

5.全代码

复制代码
import router from '@ohos.router'
import storage from '@ohos.data.storage'
import App from '@system.app'
import Prompt from '@system.prompt'
import http from '@ohos.net.http'
import { RouterInfo } from '../../Pojo/RouterInfo'
import common from '@ohos.app.ability.common'
import dataPreference from '@ohos.data.preferences'
@Entry
@Component
struct Login {
  // todo 定义域
  @State username:string=""
  @State pwd:string=""
  @State allow:boolean = false
  @State upload:boolean = true
  @State uploadTag:boolean = false
  @State lastLocalTime:string=""
  httpUtil: http.HttpRequest
  context = getContext(this) as common.UIAbilityContext
  @State last:string=''
  Router = new RouterInfo("进入主页","pages/Books/Main","主页面")

  aboutToAppear() {
    let httpRequest = http.createHttp()
    this.httpUtil = httpRequest
    // todo 初始化上一次访问时间
    this.getPreTime()
    // todo 初始化当前时间
    this.getLocalTimeToPreference()
    // todo 初始化本地数据库的密码和用户名
    this.getUserInfo()
  }

  aboutToDisappear(){
    // todo 保存当前时间作为上一次的时间
    this.closeAppAndUpdateTime()
  }



  goTo(Router:RouterInfo){
    router.pushUrl({
      url: Router.url,
      params:{
        title:Router.message
      }
    },
      router.RouterMode.Single,
      err=> {
        if (err) {
          console.log("路由失败"+err.code+':'+err.message)
        }
      })
  }


  async jwt(jwt: string) {
    try {
      const res = await this.httpUtil.request(`192.168.137.1/readers/userinfo`, {
        method: http.RequestMethod.GET,
        extraData: { no: jwt },
      });
      let data = JSON.parse(res.result.toString());
      return data;
    } catch (error) {
      throw error;
    }
  }

  // 获取当前时间并存入用户首选项
  getLocalTimeToPreference(){
    const currentDate: Date = new Date();
    const currentYear: number = currentDate.getFullYear();
    const currentMonth: number = currentDate.getMonth() + 1; // 注意:月份从 0 开始,需要加 1
    const currentDay: number = currentDate.getDate();
    const currentHour: number = currentDate.getHours();
    const currentMinute: number = currentDate.getMinutes();
    const currentSecond: number = currentDate.getSeconds();

    const curTime = `北京时间:${currentYear}-${currentMonth}-${currentDay} ${currentHour}:${currentMinute}:${currentSecond}`;

    dataPreference.getPreferences(this.context, "myBookStore").then(preferences => {
      preferences.put("curTime", curTime).then(_ => {
        preferences.flush();
      });
    }).catch((err: Error) => {
      console.error(err.message);
    });
  }

  // 获取上一次的时间--lastTime
  getPreTime(){
    dataPreference.getPreferences(this.context, "myBookStore").then(preferences => {
      if (!preferences.has("lastTime")) {
        console.log("数据并未能保存");
      } else {
        preferences.get("lastTime", 'null').then((value) => {
          this.last=value.toLocaleString()
          // AlertDialog.show({message:`上一次访问时间:${this.last}`})
          console.log("数据为:" + value);
        }).catch(_ => {
          console.log("读取失败");
        });
      }
    });
  }

  // 关闭应用时将lastTime置换为curTime,并将curTime替换为空值
  closeAppAndUpdateTime(){
    dataPreference.getPreferences(this.context, "myBookStore").then(preferences => {
      preferences.get("curTime", '').then((curTime) => {
        preferences.put("lastTime", curTime);
        preferences.put("curTime", '');
        preferences.flush();
        console.log("上一次时间已更新,当前时间已清空");
      }).catch((err: Error) => {
        console.error(err.message)
      });
    }).catch((err: Error) => {
      console.error(err.message);
    });
  }






  // todo 函数定义域
  async login() {
    if (this.username && this.pwd && this.allow) {
      try {
        const res = await this.httpUtil.request(`192.168.137.1/readers/login`, {
          method: http.RequestMethod.GET,
          extraData: { no: this.username, pwd: this.pwd },
        });
        let jsonResult = res.result.toString();
        let responseObject = JSON.parse(jsonResult);
        if (responseObject['code'] === 200) {
          // todo 解析令牌
          const data = await this.jwt(responseObject['data']);

          // todo 上下文 -- 存储令牌
          AppStorage.SetOrCreate("info",data['data']['readerno'])

          // todo 是否将密码存储至本地
          if (this.upload===true) {
            this.uploadUserInfo()
          }

          // todo 跳转
          this.goTo(this.Router)

        }
      } catch (error) {
        console.error(error);
        Prompt.showDialog({
          message: "登录失败",
        });
      }
    } else {
      if (!this.username || !this.pwd) {
        Prompt.showDialog({
          message: "请输入用户名和密码",
        });
      } else if (!this.allow) {
        Prompt.showDialog({
          message: "请勾选允许登录选项",
        });
      }
    }
  }


  uploadUserInfo(){
    // 用户存储信息到本地,使用用户首选项
    dataPreference.getPreferences(this.context, "myBookStore").then(preferences => {
      let user:{}={'username':this.username,'pwd':this.pwd}
      preferences.put("userInfo",JSON.stringify(user)).then(_ => {
        preferences.flush();
      });
    }).catch((err: Error) => {
      console.error(err.message);
    });
  }

  getUserInfo(){
    dataPreference.getPreferences(this.context, "myBookStore").then(preferences => {
      preferences.get("userInfo", '').then((userInfo) => {
        let user = JSON.parse(userInfo.toLocaleString())
        if (user) {
          this.uploadTag=true
          this.username = user['username']
          this.pwd = user['pwd']
        }
      }).catch((err: Error) => {
        console.error(err.message)
      });
    }).catch((err: Error) => {
      console.error(err.message);
    });
  }





  build() {
      Column(){
        Column() {

            Text("掌上书店")
              .fontColor('#096789')
              .fontSize(70)
          this.displayLast("上一次访问时间:"+this.last)
          if (this.uploadTag===true){
            this.displayLast("本地已经存储密码")
          }
        }.margin({ bottom: 100 })
        .height('50%')
        .justifyContent(FlexAlign.Center)

        Column()
        {
          Row()
          {
            // 用户名输入框
            TextInput({ placeholder: this.username===''? "请输入您的用户名":this.username })
              .type(InputType.Normal)
              .width('80%')
              .height(50)
              .placeholderColor(Color.Black)
              .backgroundColor('#ffd3d7d3')
              .borderRadius(10)
              .margin({ bottom: 10})
              .onChange(val=>{
                this.username=val
                console.log(val)
              })

          }

          Row()
          {
            // 密码输入框
            TextInput({ placeholder: this.pwd===''?"请输入您的密码":this.pwd })
              .type(InputType.Password)
              .width('80%')
              .height(50)
              .placeholderColor(Color.Black)
              .backgroundColor('#ffd3d7d3')
              .borderRadius(10)
              .onChange(val=>{
                this.pwd=val
                console.log(val)
              })
          }
          Row(){
            Row(){
              Checkbox().onChange((val:boolean)=>{
                this.upload=val
                console.log('Checkbox2 change is'+val)
              })
              Text("将密码存储到本地")
            }.width('98%')
            .padding({left:30})
            .height('40')
          }.margin({ bottom: 40 })

          Row()
          {
            //登录按钮
            Button("登录")
              .width(120)
              .height(40)
              .fontColor(Color.White)
              .onClick(() => {
                this.login()

              })
              .backgroundColor('#ff5eb35b')
              .margin({right:40})
              .borderStyle(BorderStyle.Dotted)

            //  注册按钮
            Button("注册")
              .width(120)
              .height(40)
              .fontColor(Color.White)
              .onClick(() => {
                router.pushUrl({
                  url: "pages/Second"
                })
              })
              .backgroundColor('#ff5eb35b')
          }
          .justifyContent(FlexAlign.SpaceEvenly)
        }
        .width("100%")
        .height("30%")

        Row(){
          Checkbox().onChange((val:boolean)=>{
            this.allow=val
            console.log('Checkbox2 change is'+val)
          })
          Text("点击代表同意相关使用条例与请求")
        }.width('90%')
        .padding({left:30})
        .height('40')

      }
      .height('100%')
        .width('100%')
        .margin({bottom:20})
        .linearGradient({
          direction:GradientDirection.RightBottom,
          colors:[[0xAEE1E1, 0.0], [0xD3E0DC, 0.3], [0xFCD1D1, 1.0]]
        })

  }


  @Builder displayLast(message) {
    Row(){
      Text(message)
        .fontColor("b#ffe7eae7")
    }.width("70%").
    height("40")
    .backgroundColor("#ffe7eae7")
    .borderRadius(20)
    .padding({left:10})
    .margin({bottom:5})
  }
}
相关推荐
用户5951433221771 分钟前
鸿蒙应用开发之@Builder自定义构建函数:值传递与引用传递与UI更新
harmonyos
Rover.x1 小时前
Netty基于SpringBoot实现WebSocket
spring boot·后端·websocket
不爱吃糖的程序媛1 小时前
Flutter 开发的鸿蒙AtomGit OAuth 授权应用
华为·harmonyos
中国胖子风清扬2 小时前
SpringAI和 Langchain4j等 AI 框架之间的差异和开发经验
java·数据库·人工智能·spring boot·spring cloud·ai·langchain
Java水解3 小时前
【SpringBoot3】Spring Boot 3.0 集成 Mybatis Plus
spring boot·后端
哈哈老师啊3 小时前
Springboot校园订餐管理系统k2pr7(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
数据库·spring boot·后端
JIngJaneIL3 小时前
基于java+ vue学生选课系统(源码+数据库+文档)
java·开发语言·前端·数据库·vue.js·spring boot
残花月伴3 小时前
天机学堂-day4(高并发优化方案)
java·spring boot·后端
阿拉斯攀登4 小时前
Spring Boot ——入门与实战
spring boot·springboot
JIngJaneIL4 小时前
基于java+ vue建筑材料管理系统(源码+数据库+文档)
java·开发语言·前端·数据库·vue.js·spring boot