华为鸿蒙应用--底部导航栏Tabs(自适应手机和平板)-ArkTs_华为鸿蒙应用 csdn 底部导航栏-CSDN博客
华为鸿蒙应用--欢迎页SplashPage+倒计时跳过(自适应手机和平板)-ArkTs_app.media.ic_splash_page_background-CSDN博客
华为鸿蒙应用--封装数据持久化工具:首选项Preferences(鸿蒙工具)-ArkTs-CSDN博客
通过登录页实现HarmonyOS网络请求、自定义Loading、MD5密码加密、emitter订阅状态变化、持久化登录状态、隐藏软键盘
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() // 隐藏软键盘
});
}
}
使用第三方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
}
});
}
}
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、上传、下载等