material-hmos/entry/src/main/ets/pages/login/LoginPage.ets

355 lines
12 KiB
Plaintext

import { TitleBar } from '../../view/TitleBar';
import systemDateTime from '@ohos.systemDateTime';
import { ToastUtils } from '../../utils/ToastUtils';
import { common } from '@kit.AbilityKit';
import { RouterUrls } from '../../common/RouterUrls';
import { Constants } from '../../common/Constants';
import LoginViewModel from '../../viewModel/LoginViewModel';
import { AppUtil, RandomUtil, StrUtil } from '@pura/harmony-utils';
import { SendCodeEntity } from '../../entity/SendCodeEntity';
import { LoginEntity } from '../../entity/LoginEntity';
import { ConfigManager } from '../../manager/UserConfigManager';
import { LoginTipDialog } from '../../dialog/LoginTipDialog';
import { LevelMode, router } from '@kit.ArkUI';
import { LoginManager } from '../../manager/LoginGlobalManager';
import { OnWXResp, WXApi, WXEventHandler } from '../../utils/wechat/WXApiEventHandlerImpl';
import * as WxOpenSdk from '@tencent/wechat_open_sdk';
import { ErrCode, SendAuthResp } from '@tencent/wechat_open_sdk';
import BuildProfile from 'BuildProfile';
import { LoadingDialog } from '../../dialog/LoadingDialog';
import { EventConstants } from '../../common/EventConstants';
import { EventReportManager } from '../../manager/EventReportManager';
@Entry
@ComponentV2
struct LoginPage {
@Local from: number = 0;
@Local isAgree: boolean = false;
@Local countDownTime: number = 0;
loginTipDialogController?: CustomDialogController | null;
viewModel: LoginViewModel = new LoginViewModel(this.getUIContext());
clickTime: number = 0;
phone: string = '';
code: string = '';
timestamp: string = '';
intervalId: number = -1;
//从微信返回的回调
onWXResp: OnWXResp = (resp) => {
//微信返回的数据
if (resp instanceof SendAuthResp && resp.state?.endsWith('phone')) {
const authResult = JSON.stringify(resp ?? {}, null , 2);
const errCode = JSON.parse(authResult).errCode as number;
if (errCode === ErrCode.ERR_OK) {
const authCode = JSON.parse(authResult).code as string;
this.viewModel.wxLogin(authCode);
} else {
ToastUtils.show(JSON.parse(authResult).errStr);
}
}
}
@Monitor('viewModel.codeEntity')
onCodeChange(monitor: IMonitor) {
const code = monitor.value()?.now as SendCodeEntity;
ToastUtils.show('验证码已发送');
this.timestamp = code.timestamp;
this.countDownTime = 60;
this.intervalId = setInterval(() => {
if (this.countDownTime > 0) {
this.countDownTime--
} else {
if (this.intervalId !== 0) {
clearInterval(this.intervalId);
}
}
}, 1000)
}
@Monitor('viewModel.phoneLoginEntity')
onPhoneLogin(monitor: IMonitor) {
const loginEntity = monitor.value()?.now as LoginEntity;
EventReportManager.eventReport(EventConstants.LOGIN, 'phone', this.phone)
LoginManager.saveToken(loginEntity.token);
LoginManager.saveLastLoginType('phone')
ConfigManager.userConfig()
.then(() => {
if (this.from === 0) {
this.toMainPage();
} else {
this.getUIContext().getRouter().back()
}
})
}
@Monitor('viewModel.wxLoginEntity')
onWxLogin(monitor: IMonitor) {
const loginEntity = monitor.value()?.now as LoginEntity;
EventReportManager.eventReport(EventConstants.LOGIN, 'weixin')
LoginManager.saveToken(loginEntity.token);
LoginManager.saveLastLoginType('weixin')
ConfigManager.userConfig()
.then(() => {
if (this.from === 0) {
this.toMainPage();
} else {
this.getUIContext().getRouter().back()
}
})
}
aboutToAppear() {
WXEventHandler.registerOnWXRespCallback(this.onWXResp)
this.initParams();
}
aboutToDisappear() {
WXEventHandler.unregisterOnWXRespCallback(this.onWXResp)
this.loginTipDialogController = null
}
initParams() {
const params = this.getUIContext().getRouter().getParams() as Record<string, Object>;
if (params) {
this.from = params.from as number;
}
}
sendCode() {
if (StrUtil.isEmpty(this.phone)) {
ToastUtils.show('请输入手机号');
return;
}
if (this.phone.length != 11) {
ToastUtils.show('请输入正确的手机号');
return;
}
this.viewModel.sendCode(this.phone);
EventReportManager.eventReport(EventConstants.GET_CODE, "code_login", this.phone)
}
toMainPage() {
this.getUIContext().getRouter().replaceUrl({ url: RouterUrls.MAIN_PAGE }, router.RouterMode.Single);
AppUtil.getContext().eventHub.emit(EventConstants.LoginSuccessEvent);
}
async wxAuth() {
if (!WXApi.isWXAppInstalled()) {
ToastUtils.show('未安装微信客户端,请先下载安装微信客户端');
return;
}
LoadingDialog.show(this.getUIContext());
let req = new WxOpenSdk.SendAuthReq;
req.isOption1 = false;
req.nonAutomatic = true;
req.scope = 'snsapi_userinfo';
req.state = BuildProfile.BUNDLE_NAME + RandomUtil.getRandomInt(0, 1000) + '_phone';
req.transaction ='';
await WXApi.sendReq(AppUtil.getContext(), req)
LoadingDialog.dismiss();
}
showLoginTipDialog(type: number) {
this.loginTipDialogController = new CustomDialogController({
builder: LoginTipDialog({
confirm: () => {
this.isAgree = true;
if (type === 0) {
this.viewModel.phoneLogin(this.phone, this.code, this.timestamp);
} else if (type === 1) {
this.wxAuth();
}
}
}),
cornerRadius: 20,
maskColor: '#CC000000',
levelMode: LevelMode.EMBEDDED,
backgroundBlurStyle: BlurStyle.NONE
})
this.loginTipDialogController.open();
}
onBackPress(): boolean | void {
if (this.from === 0) {
if (systemDateTime.getTime() - this.clickTime < 1500) {
(this.getUIContext().getHostContext() as common.UIAbilityContext).terminateSelf();
} else {
EventReportManager.eventReport(EventConstants.EXIT_APP, 'login')
this.clickTime = systemDateTime.getTime();
ToastUtils.show('双击退出应用');
}
return true;
}
}
build() {
Stack({alignContent: Alignment.TopStart}) {
Image($r('app.media.ic_login_top_bg')).width('100%')
Column() {
TitleBar({ showBack: this.from !== 0 }).width('100%')
Image($r('app.media.ic_login_logo'))
.margin({ top: 10 })
.width(80)
.height(80)
Text($r('app.string.app_name'))
.fontColor($r('app.color.color_212226'))
.fontSize(18)
.fontFamily('almmsht')
.margin({ top: 12 })
.width('auto')
Row(){
Image($r('app.media.ic_login_phone')).width(22).height(22)
TextInput({ placeholder: '请输入您的手机号' })
.type(InputType.PhoneNumber)
.fontColor($r('app.color.color_1a1a1a'))
.fontSize(16)
.placeholderColor($r('app.color.color_bcbcbc'))
.placeholderFont({ size: 16 })
.maxLength(11)
.backgroundColor(Color.Transparent)
.onChange((value: string) => {
this.phone = value;
})
}
.height(50)
.margin({ top: 50, left: 38, right: 38 })
Divider().strokeWidth(1).color($r('app.color.color_dfdfdf')).margin({ left: 38, right: 38 })
RelativeContainer() {
Row() {
Image($r('app.media.ic_login_code')).width(22).height(22)
TextInput({ placeholder: '请输入验证码' })
.type(InputType.Number)
.fontColor($r('app.color.color_1a1a1a'))
.fontSize(16)
.placeholderColor($r('app.color.color_bcbcbc'))
.placeholderFont({ size: 16 })
.maxLength(6)
.backgroundColor(Color.Transparent)
.onChange((value: string) => {
this.code = value;
})
}
.id('row_code')
Text(this.countDownTime === 0 && StrUtil.isEmpty(this.timestamp) ? '获取验证码' :
this.countDownTime > 0 ? `${this.countDownTime}s` : '重新发送')
.fontColor(this.countDownTime === 0 ? $r("app.color.color_466afd") : $r('app.color.color_999999'))
.fontSize(14)
.alignRules({
top: { anchor: 'row_code', align: VerticalAlign.Top },
right: { anchor: 'row_code', align: HorizontalAlign.End },
bottom: { anchor: 'row_code', align: VerticalAlign.Bottom },
})
.margin({ right: 16 })
.width('auto')
.onClick(() => {
if (this.countDownTime === 0) {
this.sendCode();
}
})
}.margin({ top: 26, left: 38, right: 38 }).height(50)
Divider().strokeWidth(1).color($r('app.color.color_dfdfdf')).margin({ left: 38, right: 38 })
Stack() {
Button('登录', { type: ButtonType.Capsule, stateEffect: true })
.width('100%')
.height(50)
.fontColor(Color.White)
.fontSize(16)
.fontWeight(FontWeight.Medium)
.backgroundColor($r("app.color.color_466afd"))
}.margin({ top: 40 }).padding({ left: 38, right: 38 })
.onClick(() => {
if (StrUtil.isEmpty(this.phone)) {
ToastUtils.show('请输入手机号');
return;
}
if (this.phone.length != 11) {
ToastUtils.show('请输入正确的手机号');
return;
}
if (StrUtil.isEmpty(this.code)) {
ToastUtils.show('请输入验证码');
return;
}
if (this.isAgree) {
this.viewModel.phoneLogin(this.phone, this.code, this.timestamp);
} else {
this.showLoginTipDialog(0);
}
})
Row() {
Image(this.isAgree ? $r('app.media.ic_check_true') : $r('app.media.ic_check_false')).width(16).height(16)
Text() {
Span('我已阅读并同意')
Span('《用户协议》').fontColor($r("app.color.color_466afd"))
.onClick(() => {
this.getUIContext()
.getRouter()
.pushUrl({ url: RouterUrls.WEB_PAGE, params: { title: '用户协议', url: Constants.USER_AGREEMENT } })
})
Span('和')
Span('《隐私政策》').fontColor($r("app.color.color_466afd"))
.onClick(() => {
this.getUIContext()
.getRouter()
.pushUrl({ url: RouterUrls.WEB_PAGE, params: { title: '隐私政策', url: Constants.PRIVACY_POLICY } })
})
}
.fontColor($r('app.color.color_999999'))
.fontSize(12)
.margin({ left: 4, top: 2 })
}
.alignItems(VerticalAlign.Top)
.margin({ left: 38, top: 16, right: 38 })
.onClick(() => {
this.isAgree = !this.isAgree;
})
Blank().layoutWeight(1)
Text('其他登录方式')
.fontColor('#AAAAAA')
.fontSize(10)
.width('auto')
.visibility(ConfigManager.getLoginType().length > 1 ? Visibility.Visible : Visibility.None)
Row() {
Image($r('app.media.ic_wx_login'))
.margin({ left: 25, right: 25 })
.width(38)
.height(38)
.id('iv_wx_login')
.onClick(() => {
if (this.isAgree) {
this.wxAuth()
} else {
this.showLoginTipDialog(1);
}
})
.visibility(ConfigManager.getLoginType().includes('weixin') ? Visibility.Visible : Visibility.None)
Image($r('app.media.ic_onekey_login'))
.margin({ left: 25, right: 25 })
.width(38)
.height(38)
.id('iv_onekey_login')
.visibility(Visibility.None)
}
.margin({ top: 20, bottom: 50 })
}
.width('100%')
.height('100%')
}
.backgroundColor(Color.White)
}
}