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

news/2024/7/21 8:39:00 标签: 华为, harmonyos, 鸿蒙系统

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.niftyadmin.cn/n/5291701.html

相关文章

【力扣题解】P113-路径总和 II-Java题解

&#x1f468;‍&#x1f4bb;博客主页&#xff1a;花无缺 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 花无缺 原创 收录于专栏 【力扣题解】 文章目录 【力扣题解】P113-路径总和 II-Java题解&#x1f30f;题目描述&#x1f4a1;题解&#x1f30f;总结…

不停止业务的情况下优化 Elasticsearch Reindex

在使用 Elasticsearch 时,我们总有需要修改索引映射的时候,这时我们只能进行 _reindex。事实上,这是一个相当昂贵的操作,因为根据数据量和分片数量,完整复制一个索引可能需要几个小时。 花费的时间不是大问题,但更严重的是,它会影响生产环境的性能甚至功能。 相信大家…

基于变态模态分解+bp-rf的轴承故障分类,基于变态模态分解的+BP神经网络-随机森林的轴承故障分类

目录 背影 摘要 随机森林的基本定义 随机森林实现的步骤 基于随机森林的机器启动识别 代码下载链接: 基于变态模态分解+bp-rf的轴承故障分类,基于变态模态分解的+BP神经网络-随机森林的轴承故障分类(代码完整,数据齐)资源-CSDN文库 https://download.csdn.net/download/ab…

处理HTTP错误响应:Go语言中的稳健之道

开场白&#xff1a;在Web开发中&#xff0c;HTTP错误响应是不可避免的一部分。当请求无法成功完成时&#xff0c;服务器会返回一个错误响应。今天&#xff0c;我们将深入探讨如何在Go语言中优雅地处理这些HTTP错误响应。 知识点一&#xff1a;HTTP错误响应的常见类型HTTP错误响…

ROS MoveIt!

MoveIt!是一个用于ROS的开源运动规划库&#xff0c;提供多种功能&#xff0c;包括用于运动规划的快速逆运动学分析、用于操纵的高级算法、机械手控制、动力学、控制器和运动规划。&#xff08;通过提供一个GUI来协助MoveIt!所需的各种设置&#xff0c;它允许使用RViz进行视觉反…

三维可视化智慧工地源码,数字孪生可视化大屏,微服务架构+Java+Spring Cloud +UniApp +MySql

源码技术说明 微服务架构JavaSpring Cloud UniApp MySql&#xff1b;支持多端展示&#xff08;PC端、手机端、平板端&#xff09;;数字孪生可视化大屏&#xff0c;一张图掌握项目整体情况;使用轻量化模型&#xff0c;部署三维可视化管理&#xff0c;与一线生产过程相融合&#…

Hadoop YARN CGroup 实践

文章目录 Hadoop YARN Cgroups 实践什么是 cgroupscgroups 概念YARN 使用 cgroups 背景cgroups 在 YARN 中的工作原理cgroups 在 YARN 中的实践步骤参考 Hadoop YARN Cgroups 实践 什么是 cgroups cgroups 的全名叫做 Control Groups&#xff0c; 它是 Linux 内核的一个功能&…

Erlang、RabbitMQ下载与安装教程(windows超详细)

目录 安装Erlang 1.首先安装RabbitMQ需要安装Erlang环境 2.点击下载好的.exe文件进行傻瓜式安装,一直next即可 3.配置Erlang环境变量 安装RabbitMQ 1.给出RabbitMQ官网下载址&#xff1a;Installing on Windows — RabbitMQ&#xff0c;找到 2.配置RabbitMQ环境变量&#xff0…