当前位置: 首页 > news >正文

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:stringurl:stringmessage:stringconstructor(name,url,message) {this.name=namethis.url=urlthis.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 开始,需要加 1const 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()` 和关闭应用更新时间方法

 // 获取上一次的时间--lastTimegetPreTime(){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.HttpRequestcontext = 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 开始,需要加 1const 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);});}// 获取上一次的时间--lastTimegetPreTime(){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=truethis.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=valconsole.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=valconsole.log(val)})}Row(){Row(){Checkbox().onChange((val:boolean)=>{this.upload=valconsole.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=valconsole.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})}
}

相关文章:

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

1. HarmonyOS next ArkTS ArkTS围绕应用开发在 TypeScript (简称TS)生态基础上做了进一步扩展,继承了TS的所有特性,是TS的超集 ArkTS在TS的基础上扩展了struct和很多的装饰器以达到描述UI和状态管理的目的 以下代码是一个基于…...

咖啡即将“从天而降”,无人机外卖时代来袭

如今,在我国的一些城市,无人机配送咖啡已经从设想变为现实,开启了商业化的初步尝试。 当咖啡遇上无人机,奇妙场景开启 想象一下这样的画面:你在户外的露营地,慵懒地躺在帐篷里,或是在城市公园…...

kettle经验篇:Pentaho Repository 类型资源库卡顿问题

2024年马上就结束了,终于在结束前解决了困扰许久的一个问题:kettle的Pentaho Repository 资源库异常卡顿。所以在此也梳理、记录下2024年的最后一个大问题。 项目场景 工作中一个重要内容是数据中心项目,也就必不可少的要用到ETL技术&#x…...

python opencv的sift特征检测(Scale-Invariant Feature Transform)

sift 官方文档地址:https://docs.opencv.org/4.10.0/da/df5/tutorial_py_sift_intro.html 创建SIFT实例cv2.SIFT.create()特征检测sift.detect描述子sift.compute/sift.detectAndCompute画特征cv2.drawKeypoints 原图 特征点 代码 import cv2first ./12.pngsif…...

若依定时任务

表结构 目录 quartz框架 SysJobServiceImpl实现类 使用切点,在构造器执行的时候执行定时任务的构建(这个类是交给IOC容器的,所以这个时间点就是项目启动的时候)SysJobServiceImpl实现类的init方法创建任务 /*** 创建定时任务*/public static void createScheduleJob(Scheduler …...

k8s-node2 NotReady 节点NotReady如何解决?

从集群中移除 k8s-node2 [rootk8s-master ~]# kubectl delete node k8s-node2 node "k8s-node2" deleted重置 k8s-node2 登录到 k8s-node2 上,使用以下命令重置该节点,使其退出集群并恢复到初始状态: [rootk8s-node2 ~]# sudo k…...

Ubuntu通过mDNS实现局域网local域名和octoprint域名访问

OctoPrint是一个开源的3D打印机控制软件,它提供了一个Web界面,允许用户远程监控和管理3D打印机。通过USB连接到打印机后,用户可以使用任何带有Web浏览器的设备来控制打印作业,包括开始、停止、暂停打印,以及在打印过程…...

短视频矩阵账号管理技术源码搭建详解,支持OEM

一、引言 在短视频矩阵系统中,账号管理是至关重要的一环,它涉及到多平台账号的接入、用户信息的安全存储与高效管理、权限的精准控制以及账号数据的同步与更新等关键功能。一个健壮、灵活且安全的账号管理技术架构,能够为整个短视频矩阵系统的…...

【源码 导入教程 文档 讲解】基于springboot校园新闻管理系统源码和论文

可做计算机毕业设计JAVA、PHP、爬虫、APP、小程序、C#、C、python、数据可视化、大数据、文案 传统信息的管理大部分依赖于管理人员的手工登记与管理,然而,随着近些年信息技术的迅猛发展,让许多比较老套的信息管理模式进行了更新迭代&#xf…...

Spark SQL DML语句

【图书介绍】《Spark SQL大数据分析快速上手》-CSDN博客 《Spark SQL大数据分析快速上手》【摘要 书评 试读】- 京东图书 Spark本地模式安装_spark3.2.2本地模式安装-CSDN博客 DML(Data Manipulation Language,数据操作语言)操作主要用来对…...

开发微信小程序的过程与心得

起因 作为家长,我近期参与了学校的护学岗工作。在这个过程中,我发现需要使用水印相机来记录护学活动,但市面上大多数水印相机应用都要求开通会员才能使用完整功能。作为一名程序员,我决定利用自己的技术背景,开发一个…...

【1224】数据结构(sizeof/数组的长度定义/读取字符串函数/线性表长度/左值右值/静态变量/指针与引用)

1.对一维整型数组a的正确说明是 #define SIZE 10 (换行) int a[SIZE];说法是否正确? 正确 数组的SIZE可以用宏定义,但不能用变量 2.如有定义:char str[20];,能将从键盘输入的字符串“How are you”保存到 str 数组的语句是&#x…...

Android笔记(四十一):TabLayout内的tab不滚动问题

背景 假设二级页面是上面图片的布局,当进来时TabLayout和ViewPager2绑定完就马上调setCustomItem,跳转到最后一个tab页面时,会发现tab不滚动,手动滑一下ViewPager2时才会滚动tab到正确的位置 原因分析 调用TabLayoutMediator.at…...

基于pytorch的深度学习基础3——模型创建与nn.Module

三 模型创建与nn.Module 3.1 nn.Module 模型构建两要素: 构建子模块——__init()__拼接子模块——forward() 一个module可以有多个module; 一个module相当于一个运算,都必须实现forward函数; 每一个mod…...

Debian-linux运维-docker安装和配置

腾讯云搭建docker官方文档:https://cloud.tencent.com/document/product/213/46000 阿里云安装Docker官方文档:https://help.aliyun.com/zh/ecs/use-cases/install-and-use-docker-on-a-linux-ecs-instance 天翼云常见docker源配置指导:htt…...

Docker完整技术汇总

Docker 背景引入 在实际开发过程中有三个环境,分别是:开发环境、测试环境以及生产环境,假设开发环境中开发人员用的是jdk8,而在测试环境中测试人员用的时jdk7,这就导致程序员开发完系统后将其打成jar包发给测试人员后…...

在JavaScript文件中定义方法和数据(不是在对象里定以数据和方法,不要搞错了)

在对象里定以数据和方法看这一篇 对象字面量内定义属性和方法(什么使用const等关键字,什么时候用键值对)-CSDN博客https://blog.csdn.net/m0_62961212/article/details/144788665 下是在JavaScript文件中定义方法和数据的基本方式&#xff…...

python爬虫爬抖音小店商品数据+数据可视化

爬虫代码 爬虫代码是我调用的数据接口,可能会过一段时间用不了,欢迎大家留言评论,我会不定时更新 import requests import time cookies {token: 5549EB98B15E411DA0BD05935C0F225F,tfstk: g1vopsc0sQ5SwD8TyEWSTmONZ3cA2u6CReedJ9QEgZ7byz…...

关于 覆铜与导线之间间距较小需要增加间距 的解决方法

若该文为原创文章,转载请注明原文出处 本文章博客地址:https://hpzwl.blog.csdn.net/article/details/144776995 长沙红胖子Qt(长沙创微智科)博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV…...

uniapp中Nvue白屏问题 ReferenceError: require is not defined

uniapp控制台输出如下 exception function:createInstanceContext, exception:white screen cause create instanceContext failed,check js stack ->Uncaught ReferenceError: require is not defined 或者 exception function:createInstanceContext, exception:white s…...

Local AI MusicGen开箱即用:WebUI汉化+中文Prompt提示模板集成

Local AI MusicGen开箱即用:WebUI汉化中文Prompt提示模板集成 1. 引言 想不想拥有一个私人AI作曲家?不需要你懂五线谱,也不需要昂贵的编曲软件,只要输入几个词,比如“悲伤的小提琴”或者“赛博朋克电子乐”&#xff…...

从YOLO到DeepLab:盘点CV任务中那些‘神级’特征融合技巧与避坑指南

从YOLO到DeepLab:盘点CV任务中那些‘神级’特征融合技巧与避坑指南 在计算机视觉领域,特征融合技术就像一位隐形的调音师,默默协调着神经网络中不同层次、不同来源的信息流。当你在目标检测任务中遇到小目标识别率低的问题,或在图…...

163MusicLyrics:音乐数据智能解析引擎如何重构歌词获取体验

163MusicLyrics:音乐数据智能解析引擎如何重构歌词获取体验 【免费下载链接】163MusicLyrics Windows 云音乐歌词获取【网易云、QQ音乐】 项目地址: https://gitcode.com/GitHub_Trending/16/163MusicLyrics 深夜,一位音乐制作人正在为即将发布的…...

Windows屏保设置失效?解锁注册表权限的终极指南

1. 为什么你的Windows屏保设置突然失效了? 最近有没有遇到过这种情况:明明想设置个屏保保护隐私,却发现所有选项都变成灰色不可点击?这个问题我帮不少朋友解决过,其实90%的情况都是注册表权限在作怪。Windows系统有个特…...

从零开始:用STM32CubeMX+Keil5开发计算器的5个关键陷阱与解决方案

从零开始:用STM32CubeMXKeil5开发计算器的5个关键陷阱与解决方案 当你第一次尝试用STM32CubeMX和Keil5开发一个计算器时,可能会觉得这不过是几个简单数学运算的组合。但真正动手后,你会发现从工具链配置到算法实现,处处都是"…...

Zemax新手避坑指南:从零开始搞定一个F/4的单透镜设计(附完整操作截图)

Zemax光学设计实战:F/4单透镜从入门到精通的完整避坑手册 刚接触Zemax的光学设计新手,面对复杂的界面和繁多的参数设置,往往会感到无从下手。本文将以一个具体的F/4单透镜设计任务为例,手把手带你完成从零开始的设计流程&#xff…...

别再只盯着RTK了!聊聊GNSS/INS组合导航里,紧耦合如何用1颗卫星‘吊住’你的定位

1颗卫星的逆袭:紧耦合技术如何在极端环境下守护你的定位精度 想象一下,你正驾驶一辆L4级自动驾驶汽车穿越曼哈顿的钢铁森林。高楼间的"城市峡谷"让GPS信号时断时续,传统导航系统已经开始报警——"卫星信号丢失"。但你的车…...

WRF模式选哪个边界层方案?从YSU到MYNN,手把手教你根据天气场景做选择

WRF模式边界层方案实战指南:从YSU到MYNN的精准选择策略 清晨的山谷雾气弥漫,气象站的监测数据不断跳动——这是WRF模式使用者最熟悉的场景。当你准备模拟一次强对流过程或城市热岛效应时,边界层参数化方案的选择往往成为影响结果精度的关键变…...

OpenCascade避坑指南:BRepMesh网格生成常见的5个问题与解决方法(含性能对比数据)

OpenCascade网格生成实战:5个高频问题深度解析与性能优化指南 当你在CAD开发中第一次调用BRepMesh_IncrementalMesh时,是否遇到过网格生成失败却找不到原因的情况?或是面对复杂模型时性能急剧下降的困境?这些问题往往让初学者束手…...

Iono系列工业PLC模块:Arduino生态的工业级演进

1. Iono Uno/MKR/RP 系统概述Iono 系列(Iono Uno、Iono MKR、Iono RP)并非传统意义的开发板,而是一套面向工业现场的可编程逻辑控制器(PLC)级输入/输出模块。其核心设计哲学是将 Arduino 生态的易用性、丰富库资源与工…...