华为鸿蒙应用--登录页:网络请求、自定义Loading、MD5密码加密、emitter订阅状态变化、持久化登录状态、隐藏软键盘-ArkTs

news2024/11/28 23:36:51

HarmonyOS系列

华为鸿蒙应用--底部导航栏Tabs(自适应手机和平板)-ArkTs_华为鸿蒙应用 csdn 底部导航栏-CSDN博客

华为鸿蒙应用--欢迎页SplashPage+倒计时跳过(自适应手机和平板)-ArkTs_app.media.ic_splash_page_background-CSDN博客

华为鸿蒙应用--封装数据持久化工具:首选项Preferences(鸿蒙工具)-ArkTs-CSDN博客


效果

通过登录页实现HarmonyOS网络请求、自定义Loading、MD5密码加密、emitter订阅状态变化、持久化登录状态、隐藏软键盘

0、LoginPage.ets代码

import { Constants } from '@ohos/common/src/main/ets/constants/Constants'
import { Logger } from '@ohos/common/src/main/ets/utils/Logger'
import { loginModel } from '../viewmodel/types'
import { CustomDialogView, HttpUtils, PageConstants, PFUKey, PFUtils } from '@ohos/common'
import { Md5 } from 'ts-md5';
import router from '@ohos.router'
import inputMethod from '@ohos.inputMethod'

@Extend(Text) function text16fp333() {
  .fontColor($r('app.color.color_333333'))
  .fontSize($r('app.float.middle_font_size'))
  .fontWeight(FontWeight.Medium)
}

@Extend(TextInput) function inputTrBg() {
  .margin({
    left: $r('app.float.vp_thirty_two'),
    right: $r('app.float.vp_thirty_two') })
  .height(50)
  .backgroundColor($r('app.color.color_transparent'))
  .fontSize($r('app.float.middle_font_size'))
  .fontWeight(FontWeight.Medium)
}

@Extend(Line) function line() {
  .width(Constants.FULL_PARENT)
  .height($r('app.float.vp_zero_point_five'))
  .backgroundColor($r('app.color.color_E0E0E0'))
}


@Entry
@Component
struct LoginPage {
  private loginModel: loginModel;
  private account: string;
  private password: string;

  build() {
    RelativeContainer() {
      Column() {
        Image($r('app.media.img_logo'))
          .height(44)

        Text($r('app.string.str_login_by_password'))
          .fontColor($r('app.color.black'))
          .fontSize($r('app.float.bigger_font_size'))
          .margin({ top: $r('app.float.vp_ten') })
          .key("123")

      }
      .alignItems(HorizontalAlign.Start)
      .alignRules({
        top: { anchor: '__container__', align: VerticalAlign.Top },
        left: { anchor: '__container__', align: HorizontalAlign.Start }
      })
      .margin({ top: 80, left: $r('app.float.vp_thirty_two') })
      .id("c_top")

      Column() {
        Row() {
          Text($r('app.string.str_account'))
            .text16fp333()
          TextInput({ placeholder: $r('app.string.str_account_hint'), text: "13595432224" })
            .inputTrBg()
            .type(InputType.PhoneNumber)
            .onChange((value: string) => {
              this.account = value
            })
        };
        Line()
          .line()
        Row() {
          Text($r('app.string.str_password'))
            .text16fp333()
          TextInput({ placeholder: $r('app.string.str_password_hint'), text: "dho123456" })
            .inputTrBg()
            .type(InputType.Password)
            .onChange((value: string) => {
              this.password = value
            })
        };
        Line()
          .line()

        Button($r('app.string.str_login_now'), { type: ButtonType.Normal, stateEffect: true })
          .borderRadius($r('app.float.vp_five'))
          .backgroundColor($r('app.color.color_3662EC'))
          .width(Constants.FULL_PARENT)
          .margin({
            top: $r('app.float.vp_twenty')
          })
          .height($r('app.float.vp_forty'))
          .onClick(() => {
            let params = {
              user_id: this.account,
              password: Md5.hashStr(this.password) // md5加密密码
            }
            HttpUtils.post(HttpUtils.LOGIN_BY_PASSWORD_URL, params, true)
              .then((res) => {
                this.loginModel = JSON.parse(res)
                PFUtils.put(PFUKey.IS_LOGIN, true); // 首选项记录已经登录
                HttpUtils.defaultParams("token", this.loginModel.token) // 网络请求默认参数token(authorization)
                router.replaceUrl({ url: PageConstants.MAIN_PAGE_URL }) // 跳转首页
              })
          });
        Button($r('app.string.str_register_now'), { type: ButtonType.Normal, stateEffect: true })
          .borderRadius($r('app.float.vp_five'))
          .backgroundColor($r('app.color.color_transparent'))
          .borderStyle(BorderStyle.Solid)
          .borderWidth($r('app.float.vp_one'))
          .borderColor($r('app.color.color_3662EC'))
          .borderRadius($r('app.float.vp_five'))
          .width(Constants.FULL_PARENT)
          .fontColor($r('app.color.color_3662EC'))
          .margin({
            top: $r('app.float.vp_twenty')
          })
          .height($r('app.float.vp_forty'))
          .onClick(() => {
            HttpUtils.post(HttpUtils.USER_INFO_URL)
              .then((res) => {
                Logger.error(Constants.TAG, JSON.stringify(res))
              })
          })
      }
      .alignRules({
        center: { anchor: '__container__', align: VerticalAlign.Center },
        left: { anchor: '__container__', align: HorizontalAlign.Start }
      })
      .margin({
        left: $r('app.float.vp_thirty_two'),
        right: $r('app.float.vp_thirty_two')
      })
      .alignItems(HorizontalAlign.Start)
      .id("c_center")

      CustomDialogView().id("load");
    }
    .height('100%')
    .width("100%")
    .backgroundColor($r('app.color.color_F3F4F6'))
    .onClick(() => {
      let im = inputMethod.getController()
      im.stopInputSession() // 隐藏软键盘
    });

  }
}

1、网络请求HttpsUtils.ets

使用第三方Axios库:OpenHarmony-SIG/ohos_axios

使用该库时,在配置全局请求参数时失效(可能是我使用方法错误),所以自定义补充实现了:defaultParams方法

同时实现了网络请求的loading

import emitter from '@ohos.events.emitter';
import { EmitterId } from '../constants/EmitterId';
import axios, {
  AxiosError,
  AxiosResponse,
  AxiosProgressEvent,
  InternalAxiosRequestConfig,
  AxiosRequestConfig,
} from '@ohos/axios'
import { Constants } from '../constants/Constants';
import { HttpData, loginModel } from '../viewmodel/types';
import promptAction from '@ohos.promptAction';
import { Logger } from './Logger';
import { PFUtils } from './PFUtils';
import { PFUKey } from '../constants/PFUKey';

export interface param {
  paramKey: string,
  paramValue: string,
}

export class HttpUtils {
  static readonly BASE_URL: string = "http://192.168.1.10:10110/"; // 基础Url
  static readonly LOGIN_BY_PASSWORD_URL: string = "password/login"; // 密码登录
  static readonly USER_INFO_URL: string = "user/data"; // 用户信息

  static async defaultParams(key: string, value: string) {
    let param = { paramKey: key, paramValue: value }
    let arrParams: Array<param>
    PFUtils.get(PFUKey.DEFAULT_PARAMS).then((res: string) => {
      if (res === undefined) {
        arrParams = []
      } else {
        arrParams = JSON.parse(res);
      }
      let index = arrParams.findIndex(item => item.paramKey === key)
      if (index === -1) {
        arrParams.push(param)
      } else {
        arrParams[index].paramValue = value;
      }
      PFUtils.put(PFUKey.DEFAULT_PARAMS, JSON.stringify(arrParams))
    })
  }

  static async post(url: string, params?: any, noDefaultParam?: boolean) {
    if (params === undefined) {
      params = {}
    }
    let resp;
    this.showLoad(true);
    if (!noDefaultParam) {
      await PFUtils.get(PFUKey.DEFAULT_PARAMS).then((value: string) => {
        if (value !== undefined) {
          let arrParams: Array<param>;
          arrParams = JSON.parse(value);
          for (let index = 0; index < arrParams.length; index++) {
            const element = arrParams[index];
            params[element.paramKey] = element.paramValue
          }
        }
      })
    }
    Logger.debug(Constants.HTTP_TAG, "Url:" + this.BASE_URL + url)
    Logger.debug(Constants.HTTP_TAG, "Param:" + JSON.stringify(params))
    await axios.post(this.BASE_URL + url, params)
      .then((res: AxiosResponse<HttpData>) => {
        resp = JSON.stringify(res.data.data);
        setTimeout(() => {
          this.showLoad(false);
          promptAction.showToast({
            message: res.data.message
          })
        }, 500); // 延迟500毫秒隐藏Loading,
        Logger.debug(Constants.HTTP_TAG, "Data:" + resp)
      }).catch((err: AxiosError) => {
        setTimeout(() => {
          this.showLoad(false);
          promptAction.showToast({
            message: err.message
          })
        }, 500);
        resp = JSON.stringify(err)
        Logger.error(Constants.HTTP_TAG, "Err:" + JSON.stringify(err));
      });

    return resp;
  }

  static showLoad(show: boolean) {
    emitter.emit({
      eventId: EmitterId.LOAD_PROGRESS,
      priority: emitter.EventPriority.IMMEDIATE
    }, {
      data: {
        "showLoad": show
      }
    });
  }
}

0、HttpData、loginModel


export interface HttpData<T = any> {
  code?: number,
  message?: string,
  data?: T
}

export interface loginModel {
  token?: string,
  user_id?: string,
}


1.自定义loading

import emitter from '@ohos.events.emitter';
import { EmitterId } from '../../constants/EmitterId';
import { LoadingProgressDialog } from './LoadingProgressDialog'

export class CustomDialogCallback {
  confirmCallback: Function = () => {
  };
  cancelCallback: Function = () => {
  };
}

@Component
export struct CustomDialogView {
  @Provide dialogCallBack: CustomDialogCallback = new CustomDialogCallback();
  loadingDialog: CustomDialogController = new CustomDialogController({
    builder: LoadingProgressDialog(),
    autoCancel: true,
    customStyle: true
  });

  aboutToAppear() {
    let innerEvent = {
      eventId: EmitterId.LOAD_PROGRESS
    };
    emitter.on(innerEvent, (eventData) => {
      if (eventData.data.showLoad) {
        if (this.loadingDialog) {
          this.loadingDialog.open();
        }
      } else {
        if (this.loadingDialog) {
          this.loadingDialog.close();
        }
      }
    });
  }

  aboutToDisappear() {
    emitter.off(EmitterId.LOAD_PROGRESS)
  }

  build() {
  }
}


@CustomDialog
export struct LoadingProgressDialog {
  controller: CustomDialogController = new CustomDialogController({ builder: '' });

  build() {
    Column() {
      LoadingProgress()
        .width(80)
        .height(80)
        .color("#FF0000");
      Text("加载中...")
        .margin({ top: $r('app.float.vp_ten'), bottom: $r('app.float.vp_ten') });
    }
    .width(140)
    .height(160)
    .alignItems(HorizontalAlign.Center)
    .justifyContent(FlexAlign.Center)
    .borderRadius($r('app.float.vp_ten'))
    .backgroundColor($r('app.color.white'))
  }
}
 

总结

后面继续补充网络请求其他方法:get、delete、上传、下载等

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

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

相关文章

云手机引领社交平台运营新潮流

在网络高度发展的今天&#xff0c;社交平台已经成为企业宣传推广的关键渠道之一。传统的社交运营方式已经无法满足效率的要求&#xff0c;云手机因而开始引领社交平台运营的新潮流。本文将深入探讨云手机如何重新定义社交平台运营&#xff0c;为用户和企业带来更为便捷、智能的…

GoLang学习之路,对Elasticsearch的使用,一文足以(包括泛型使用思想)(二)

书写上回&#xff0c;上回讲到&#xff0c;Elasticsearch的使用前提即&#xff1a;语法&#xff0c;表结构&#xff0c;使用类型结构等。要学这个必须要看前面这个&#xff1a;GoLang学习之路&#xff0c;对Elasticsearch的使用&#xff0c;一文足以&#xff08;包括泛型使用思…

腾讯云服务器和轻量服务器选哪个好(各自的优势区别)

腾讯云轻量服务器和云服务器CVM该怎么选&#xff1f;不差钱选云服务器CVM&#xff0c;追求性价比选择轻量应用服务器&#xff0c;轻量真优惠呀&#xff0c;活动 https://curl.qcloud.com/oRMoSucP 轻量应用服务器2核2G3M价格62元一年、2核2G4M价格118元一年&#xff0c;540元三…

2023.12.27 关于 Redis 数据类型 List 常用命令

目录 List 类型基本概念 List 类型特点 List 操作命令 LPUSH LPUSHX RPUSH RPUSHX LRANGE LPOP RPOP LINDEX LINSERT LREM LTRIM LSET 阻塞版本的命令 阻塞版本 和 非阻塞版本的区别 BLPOP & BRPOP List 类型基本概念 Redis 中的列表&#xff08;list&am…

适用于各种危险区域的火焰识别摄像机,实时监测、火灾预防、安全监控,为安全保驾护航

火灾是一种极具破坏力的灾难&#xff0c;对人们的生命和财产造成了严重的威胁。为了更好地预防和防范火灾&#xff0c;火焰识别摄像机作为一种先进的监控设备&#xff0c;正逐渐受到人们的重视和应用。本文将介绍火焰识别摄像机在安全监控和火灾预防方面的全面应用方案。 一、火…

django之drf框架(排序、过滤、分页、异常处理)

排序 排序的快速使用 1.必须是继承GenericAPIView及其子类才能是用排序 导入OrderingFilter类&#xff0c;from rest_framework.filters import OrderingFilter 2.在类中配置类属性 filter_backends[OrderingFilter] 3.类中写属性 ordering_fields [price,id] # 必须是表的…

华为云CCE-集群内访问-根据ip访问同个pod

华为云CCE-集群内访问-根据ip访问同个pod 问题描述&#xff1a;架构如下&#xff1a;解决方法&#xff1a; 问题描述&#xff1a; 使用service集群内访问时&#xff0c;由于启用了两个pod&#xff0c;导致请求轮询在两个pod之间&#xff0c;无法返回正确的结果。 架构如下&am…

Appium+python自动化(七)- 初识琵琶女Appium(千呼万唤始出来,犹抱琵琶半遮面)- 上(超详解)

简介 “千呼万唤始出来&#xff0c;犹抱琵琶半遮面”&#xff0c;经过前边的各项准备工作&#xff0c;终于才把appium这位琵琶女请出来。那么下边就由宏哥给各位看官、小伙伴们和童鞋们来引荐这位美女&#xff08;帅哥&#xff09;。这一篇主要是对前边的内容做一个小小的总结&…

功能测试知识超详细总结

一、测试项目启动与研读需求文档 &#xff08;一&#xff09; 组建测试团队 1、测试团队中的角色 2、测试团队的基本责任 尽早地发现软件程序、系统或产品中所有的问题。督促和协助开发人员尽快地解决程序中的缺陷。帮助项目管理人员制定合理的开发和测试计划。对缺陷进行跟…

远程桌面的3389端口如何修改

远程桌面是windows的一个功能组件&#xff0c;通过这个组件可以远程控制某台电脑的电脑桌面&#xff0c;使用过windows远程桌面的人都清楚&#xff0c;大家都知道3389是远程桌面的默认端口号&#xff0c;如果将这个端口在路由器中映射出去&#xff0c;将极大的增加服务器的风险…

.NET Core NPOI导出复杂Excel

一、引入NPOI NuGet&#xff1a; NPOI GitHub源码地址&#xff1a; GitHub - tonyqus/npoi: a .NET library that can read/write Office formats without Microsoft Office installed. No COM, no interop. 版本说明&#xff1a; NPOI 2.4.1 &#xff08;注意不同版本可能使用…

elasticsearch-hadoop.jar 6.8版本编译异常

## 背景 重新编译 elasticsearch-hadoop 包&#xff1b; GitHub - elastic/elasticsearch-hadoop at 6.8 编译 7.17 版本时很正常&#xff0c;注意设置下环境变量就好&#xff0c;JAVA8_HOME/.... 编译 6.8 版本时&#xff08;要求jdk8 / jdk9&#xff09;&#xff0c;出现…

经典目标检测YOLO系列(一)YOLOV1的复现(1)总体架构

经典目标检测YOLO系列(一)实现YOLOV1网络(1)总体架构 实现原版的YOLOv1并没有多大的意义&#xff0c;因此&#xff0c;根据《YOLO目标检测》(ISBN:9787115627094)一书&#xff0c;在不脱离YOLOv1的大部分核心理念的前提下&#xff0c;重构一款较新的YOLOv1检测器&#xff0c;来…

毕业/课程设计——基于STM32的智能灯光控制系统(物联网、智能家居、手机APP控制、语音控制)

文章首先介绍本系统所包含的功能&#xff0c;主要包含六方面功能&#xff0c;之后逐步分享开发过程&#xff0c;其流程如下&#xff1a;点亮灯带&#xff08;三极管&#xff09;→调节灯光亮度&#xff08;PWM&#xff09;→为系统添加远程控制功能→为系统添加语音识别功能→添…

消防数据监测可视化大屏:守护城市安全的智慧之眼

在数字化时代&#xff0c;数据已经成为决策的关键。特别是在消防领域&#xff0c;快速、准确的数据分析对于及时应对火情、挽救生命财产具有不可估量的价值。为此&#xff0c;消防数据监测可视化大屏应运而生&#xff0c;成为城市安全的守护者。 一、什么是消防数据监测可视化大…

云轴科技海通期货 | 一云多芯信创云平台方案入选上海金融科技优秀解决方案

近日&#xff0c;在上海金融科技产业联盟主办的第五届上海金融科技国际论坛上&#xff0c;上海市地方金融监督管理局、中国人民银行上海总部共同发布了2023年度上海金融科技优秀应用场景及解决方案入选名单&#xff0c;其中云轴科技ZStack联合海通期货申报的“一云多芯信创云平…

centos下docker安装Rocketmq总结,以及如何更换mq端口

默认你已经装好了docker哈 安装docker-compose sudo curl -L https://github.com/docker/compose/releases/download/1.25.1-rc1/docker-compose-uname -s-uname -m -o /usr/local/bin/docker-composechmod x /usr/local/bin/docker-composedocker-compose --version成功打印…

MidJourney笔记(9)-daily_theme-docs-describe

/daily_theme 切换 #daily-theme 频道更新的通知。 但我发现在对话框那里,是没有这个命令的: 但官网是有介绍,不知道是不是版本问题还是这个命令已经无效。 但后来,我发现这个命令是要在Midjourney服务对话框那里才有,在我们后面添加的Mid

Redis布隆过滤器BloomFilter

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是爱吃芝士的土豆倪&#xff0c;24届校招生Java选手&#xff0c;很高兴认识大家&#x1f4d5;系列专栏&#xff1a;Spring源码、JUC源码、Kafka原理、分布式技术原理、数据库技术&#x1f525;如果感觉博主的文章还不错的…

Apache OFBiz RCE漏洞复现(CVE-2023-51467)

0x01 产品简介 Apache OFBiz是一个电子商务平台,用于构建大中型企业级、跨平台、跨数据库、跨应用服务器的多层、分布式电子商务类应用系统。 0x02 漏洞概述 漏洞成因 该系统的身份验证机制存在缺陷,可能允许未授权用户通过绕过标准登录流程来获取后台访问权限。此外,在…