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

news2024/9/25 9:41:11

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})
  }
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【和鲸冬令营】通过数据打造爆款社交APP用户行为分析报告

【🐋和鲸冬令营】通过数据打造爆款社交APP用户行为分析报告 文章目录 【🐋和鲸冬令营】通过数据打造爆款社交APP用户行为分析报告1 业务背景2 数据说明3 数据探索性分析4 用户行为分析4.1 用户属性与行为关系分析4.2 转化行为在不同用户属性群体中的分布…

Android之MQTT的使用

MQTT的简单介绍 MQTT是广泛应用于物联网的传输协议,基于TCP MQTT有一个代理服务器,其客户端可以订阅主题或向一个主题发送消息,从而实现通信 MQTT 设计了 3 个 QoS 等级。 QoS 0:消息最多传递一次,如果当时客户端不…

Jmeter基础使用---Token鉴权接口关联

接口测试流程: 查看API接口文档,熟悉接口业务(地址、端口、参数、鉴权、状态码)设计接口测试用例(正例:正确的结果;反例:鉴权异常、参数异常、兼容异常、其他异常)使用接…

Java中的List

List集合的特有方法 方法介绍 方法名描述void add(int index,E element)在此集合中的指定位置插入指定的元素E remove(int index)删除指定索引处的元素,返回被删除的元素E set(int index,E element)修改指定索引处的元素,返回被修改的元素E get(int inde…

rtt的io设备框架面向对象学习-io设备管理层

目录 1.设备基类2.rtt基类2.1 rtt基类定义2.2 对象容器定义2.3 rtt基类构造函数 3.io设备管理接口4.总结 这层我的理解就是rtt基类和设备基类所在,所以抽离出来好点,不然每个设备类都要重复它。 1.设备基类 /include/rtdef.h中定义了设备基类struct rt_…

Spring:EnclosingClass工具类分辨

Spring:EnclosingClass工具类分辨 1 前言 通过Spring的工具分辨EnclosingClass类。 测试类如下: package com.xiaoxu.test.enclosingClass;/*** author xiaoxu* date 2024-01-18* java_demo2:com.xiaoxu.test.enclosingClass.Outter*/ public class …

计算机专业必看的几部电影推荐

计算机专业必看的几部电影,就像一场精彩的编程盛宴!《黑客帝国》让你穿越虚拟世界,感受高科技的魅力;《社交网络》揭示了互联网巨头的创业之路,《源代码》带你穿越时间解救世界,这些电影不仅带我们穿越到科…

模型部署 - onnx 的导出和分析 -(1) - PyTorch 导出 ONNX - 学习记录

onnx 的导出和分析 一、PyTorch 导出 ONNX 的方法1.1、一个简单的例子 -- 将线性模型转成 onnx1.2、导出多个输出头的模型1.3、导出含有动态维度的模型 二、pytorch 导出 onnx 不成功的时候如何解决2.1、修改 opset 的版本2.2、替换 pytorch 中的算子组合2.3、在 pytorch 登记&…

SpringBoot+Maven多环境配置模式

我这里有两个配置文件 然后在最外层的父级POM文件里面把这个两个配置文件写上 <profiles><profile><id>druid</id><properties><spring.profiles.active>druid</spring.profiles.active></properties><activation><…

管理系统提升:列表页构成要素,拒绝千篇一律

大家伙&#xff0c;我是大千UI工场&#xff0c;专注UI知识案例分享和接单&#xff0c;本期带来B端系统列表页的分享&#xff0c;欢迎大家关注、互动交流。 一、什么是列表页 管理系统列表页是指管理系统中用于展示和管理数据的页面&#xff0c;通常以表格或列表的形式呈现。列…

经典语义分割(一)利用pytorch复现全卷积神经网络FCN

经典语义分割(一)利用pytorch复现全卷积神经网络FCN 这里选择B站up主[霹雳吧啦Wz]根据pytorch官方torchvision模块中实现的FCN源码。 Github连接&#xff1a;FCN源码 1 FCN模型搭建 1.1 FCN网络图 pytorch官方实现的FCN网络图&#xff0c;如下所示。 1.2 backbone FCN原…

斐波那契数列模型---使用最小花费爬楼梯

746. 使用最小花费爬楼梯 - 力扣&#xff08;LeetCode&#xff09; 1、状态表示&#xff1a; 题目意思即&#xff1a;cost[i]代表从第i层向上爬1阶或者2阶&#xff0c;需要花费多少力气。如cost[0]&#xff0c;代表从第0阶爬到第1阶或者第2阶需要cost[0]的力气。 一共有cost.…

Java - List集合与Array数组的相互转换

一、List 转 Array 使用集合转数组的方法&#xff0c;必须使用集合的 toArray(T[] array)&#xff0c;传入的是类型完全一样的数组&#xff0c;大小就是 list.size() public static void main(String[] args) throws Exception {List<String> list new ArrayList<S…

梯度下降算法(带你 原理 实践)

目录 一、引言 二、梯度下降算法的原理 三、梯度下降算法的实现 四、梯度下降算法的优缺点 优点&#xff1a; 缺点&#xff1a; 五、梯度下降算法的改进策略 1 随机梯度下降&#xff08;Stochastic Gradient Descent, SGD&#xff09; 2 批量梯度下降&#xff08;Batch…

【解读】工信部数据安全能力提升实施方案

近日&#xff0c;工信部印发《工业领域数据安全能力提升实施方案&#xff08;2024-2026年&#xff09;》&#xff0c;提出到2026年底&#xff0c;我国工业领域数据安全保障体系基本建立&#xff0c;基本实现各工业行业规上企业数据安全要求宣贯全覆盖。数据安全保护意识普遍提高…

vue api封装

api封装 由于一个项目里api是很多的&#xff0c;随处都在调&#xff0c;如果按照之前的写法&#xff0c;在每个组件中去调api&#xff0c;一旦api有改动&#xff0c;遍地都要去改&#xff0c;所以api应该也要封装一下&#xff0c;将api的调用封装在函数中&#xff0c;将函数集…

sql 行列互换

在SQL中进行行列互换可以使用PIVOT函数。下面是一个示例查询及其对应的结果&#xff1a; 创建测试表格 CREATE TABLE test_table (id INT PRIMARY KEY,name VARCHAR(50),category VARCHAR(50) );向测试表格插入数据 INSERT INTO test_table VALUES (1, A, Category A); INSE…

Go语言必知必会100问题-15 缺少代码文档

缺少代码文档 文档&#xff08;代码注释&#xff09;是编码的一个重要方面&#xff0c;它可以降低客户端使用API的复杂度&#xff0c;也有助于项目维护。在Go语言中&#xff0c;我们应该遵循一些规则使得我们的代码更地道。下面一起来看看这些规则。 每个可导出的元素必须添加…

YOLOv9有效提点|加入MobileViT 、SK 、Double Attention Networks、CoTAttention等几十种注意力机制(五)

专栏介绍&#xff1a;YOLOv9改进系列 | 包含深度学习最新创新&#xff0c;主力高效涨点&#xff01;&#xff01;&#xff01; 一、本文介绍 本文只有代码及注意力模块简介&#xff0c;YOLOv9中的添加教程&#xff1a;可以看这篇文章。 YOLOv9有效提点|加入SE、CBAM、ECA、SimA…

JVM相关问题

JVM相关问题 一、Java继承时父子类的初始化顺序是怎样的&#xff1f;二、JVM类加载的双亲委派模型&#xff1f;三、JDK为什么要设计双亲委派模型&#xff0c;有什么好处&#xff1f;四、可以打破JVM双亲委派模型吗&#xff1f;如何打破JVM双亲委派模型&#xff1f;五、什么是内…