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 请求对象、获取上次访问时间、初始化本地时间等
}

4. 页面跳转方法 `goTo()`:

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

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

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

6. 存储当前时间到用户首选项方法 `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);
    });
  }

7. 获取上一次访问时间方法 `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);
    });
  }

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

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

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

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

9. 构建页面布局的方法 `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})
  }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/944500.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

3.微服务灰度发布落地实践(组件灰度增强)

文章目录 前言调用链示图dubbo服务之间的的调链cloud 服务之间的调用链 网关servlet容器: 标签续传1.定义插件2.实现灰度增强拦截 线程池: 标签续传1.拦截Runnable或Callable,接口增强实现标签续传;Callable 插件定义Runnable 插件定义拦载Callabl或Runnable构造(可共用)拦载ru…

不修改内核镜像的情况下,使用内核模块实现“及时”的调度时间片超时事件上报

一、背景 之前的博客 不修改内核镜像的情况下,使用内核模块实现高效监控调度时延-CSDN博客 里,我们讲了不修改内核镜像高效监控每次的调度时延的方法。这篇博客里,我们对于调度时间片也做这么一个不修改内核镜像的改进。关于调度时间片过长的…

机器视觉中的单线程、多线程与跨线程:原理与应用解析

在机器视觉应用中,程序的运行效率直接影响到系统的实时性和稳定性。随着任务复杂度的提高,单线程处理往往无法满足高性能需求,多线程技术因此被广泛应用。此外,跨线程操作(如在多线程中更新界面或共享资源)…

喜报 | 擎创科技入围上海市优秀信创解决方案

近日,由上海市经信委组织的“2024年上海市优秀信创解决方案”征集遴选活动圆满落幕,擎创科技凭借实践经验优秀的《擎创夏洛克智能预警与应急处置解决方案》成功入选“2024年上海市优秀信创解决方案”名单。 为激发创新活力,发挥标杆作用&…

linux-21 目录管理(一)mkdir命令,创建空目录

对linux而言,对一个系统管理来讲,最关键的还是文件管理。那所以我们接下来就来看看如何实现文件管理。当然,在文件管理之前,我们说过,文件通常都放在目录下,对吧?所以先了解目录,可能…

【Redis】 数据淘汰策略

面试官询问缓存过多而内存有限时内存被占满的处理办法,引出 Redis 数据淘汰策略。 数据淘汰策略与数据过期策略不同, 过期策略针对设置过期时间的 key 删除, 淘汰策略是在内存不够时按规则删除内存数据。 八种数据淘汰策略介绍 no evision&…

一网多平面

“一网多平面”是一种网络架构概念,具体指的是在一张物理网络之上,逻辑划分出“1N”个平面。以下是对“一网多平面”的详细解释: 定义与构成 01一网多平面 指的是在统一的物理网络基础设施上,通过逻辑划分形成多个独立的网络平面…

小程序配置文件 —— 12 全局配置 - pages配置

全局配置 - pages配置 在根目录下的 app.json 文件中有一个 pages 字段,这里我们介绍一下 pages 字段的具体用法; pages 字段:用来指定小程序由哪些页面组成,用来让小程序知道由哪些页面组成以及页面定义在哪个目录,…

MyBatis如何处理延迟加载?

大家好,我是锋哥。今天分享关于【MyBatis如何处理延迟加载?】面试题。希望对大家有帮助; MyBatis如何处理延迟加载? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 MyBatis 支持 延迟加载(Lazy Loading&am…

Quartz任务调度框架实现任务动态执行

说明:之前使用Quartz,都是写好Job,指定一个时间点,到点执行。最近有个需求,需要根据前端用户设置的时间点去执行,也就是说任务执行的时间点是动态变化的。本文介绍如何用Quartz任务调度框架实现任务动态执行…

vue3使用video-player实现视频播放(可拖动视频窗口、调整大小)

1.安装video-player npm install video.js videojs-player/vue --save在main.js中配置全局引入 // 导入视频播放组件 import VueVideoPlayer from videojs-player/vue import video.js/dist/video-js.cssconst app createApp(App) // 视频播放组件 app.use(VueVideoPlayer)2…

从入门到精通:Vim 高效文本编辑全面指南

文章目录 前言🧬一、Vim 的编辑哲学:模式分离与高效键盘操作🧬二、基础命令与快捷键:从简单到熟悉🧬三、进阶功能:多文件、分屏与可视化模式🧬四、自定义配置与 .vimrc:打造你的专属…

正则表达式(三剑客之sed)

1.sed工具的使用 1.1 sed工具 1)命令格式:sed -n ‘n’ p filename 1.2 打印某行 1)打印第二行 [rootlocalhost ~]# sed -n 2p /etc/passwd 2)第二行重复打印 [rootlocalhost ~]# sed 2p /etc/passwd 3)所有行全部…

珞珈一号夜光遥感数据地理配准,栅格数据地理配准

目录 一、夜光数据下载: 二、夜光遥感数据地理配准 三、计算夜光数据值 四、辐射定标 五、以表格显示分区统计 五、结果验证 夜光数据位置和路网位置不匹配,虽然都是WGS84坐标系,不匹配!!!不要看到就直接…

虚幻引擎是什么?

Unreal Engine,是一款由Epic Games开发的游戏引擎。该引擎主要是为了开发第一人称射击游戏而设计,但现在已经被成功地应用于开发模拟游戏、恐怖游戏、角色扮演游戏等多种不同类型的游戏。虚幻引擎除了被用于开发游戏,现在也用于电影的虚拟制片…

多个微服务 Mybatis 过程中出现了Invalid bound statement (not found)的特殊问题

针对多个微服务的场景,记录一下这个特殊问题: 如果启动类上用了这个MapperScan注解 在resource 目录下必须建相同的 com.demo.biz.mapper 目录结构,否则会加载不到XML资源文件 。 并且切记是com/demo/biz 这样的格式创建,不要使用…

使用Excel制作通达信自定义外部数据,安排!!!

Excel相信大家电脑上都有这个工具,相比敲编程代码,用这个去做自定义数据对大多数人,应该是比较友好的。自定义数据分为外部序列数据,看了一下内容理解起来比较多,分两期给大家介绍。为了照顾电脑基础薄弱的朋友&#x…

win10、win11-鼠标右键还原、暂停更新

系统优化 win 10jihuo win 11jihuo鼠标右键还原暂停更新 update 2024.12.28win 10 jihuo winx,打开powershell管理员,输入以下命令,选择1并等待 irm https://get.activated.win | iex参考:https://www.bilibili.com/video/BV1TN411M72J/?sp…

QT集成IntelRealSense双目摄像头2,集成OpenGL

上一篇文章写了如何把IntelRealSense摄像头的SDK集成到QT项目,并成功采集数据,在没有用OpenCV的情况下完成色彩数据,以及深度数据的显示。 具体地址:https://blog.csdn.net/qujia121qu/article/details/144734163 本次主要写如何…

数据分析的分类和EDIT思维框架

为了服务于企业不同层次的决策,商业数据分析过程需要提供相应的数据科学产出物。 一般而言,数据分析需要经历从需求层、数据层、分析层到输出层四个阶段。 第一个阶段是需求层——确定目标,具体目标需要依据具体的层次进行分析&#xff1a…