From e5fbd40c6027f491d9dbab021c1a48b14c2332b9 Mon Sep 17 00:00:00 2001 From: wayne <wayne8692wayne8692@gmail.com> Date: 星期一, 29 十一月 2021 16:40:53 +0800 Subject: [PATCH] Merge remote-tracking branch 'origin/master' --- PAMapp/pages/login/index.vue | 487 +++++++++++++++++++++++++++++++++++------------------- 1 files changed, 315 insertions(+), 172 deletions(-) diff --git a/PAMapp/pages/login/index.vue b/PAMapp/pages/login/index.vue index f1cb6f7..42d1190 100644 --- a/PAMapp/pages/login/index.vue +++ b/PAMapp/pages/login/index.vue @@ -24,7 +24,9 @@ 'is-invalid': !phoneValid }" v-model="phoneNumber" - placeholder="隢撓�����Ⅳ"> + placeholder="隢撓�����Ⅳ" + :disabled="showPhoneOtpCodeField" + > <div class="error mt-5 mb-5"> <span v-show="!phoneValid">����Ⅳ�撘�炊</span> </div> @@ -38,6 +40,7 @@ }" v-model="email" placeholder="隢撓� Email ���" + :disabled="showEmailVerifyField" > <div class="error mt-5 mb-5"> <span v-show="!emailValid">Email�撘�炊</span> @@ -51,11 +54,11 @@ <el-row type="flex" justify="space-between"> <div class="mdTxt">頛詨撽�Ⅳ</div> <div class="otp-count-timer"> - {{otpCounter}} + {{phoneCounter}} </div> </el-row> - <el-row class="mb-30"> + <el-row> <input class="pam-input mt-10" :class="{ @@ -65,6 +68,9 @@ placeholder="隢撓�撽�Ⅳ" > </el-row> + <div class="error mt-5 mb-10"> + <span v-show="otpCounterSec === 0">撽�Ⅳ撌脤�����撽�Ⅳ</span> + </div> <el-row> <el-button @@ -72,7 +78,10 @@ @click="resentOtp('MOBILE')" icon="icon-arrow" > - ��撽�Ⅳ<span class="pam-field-title__hint pl-5">({{ otpResendCounter }})</span> + ��撽�Ⅳ<span + class="pam-field-title__hint pl-5" + v-if="otpResendCounter !== 0" + >({{ otpResendCounter }})</span> </el-button> </el-row> </div> @@ -93,14 +102,37 @@ <!-- email 撽�Ⅳ --> <template v-if="connectDevice === 'EMAIL'"> <el-row v-show="showEmailVerifyField"> + <el-row type="flex" justify="space-between"> + <div class="mdTxt">頛詨撽�Ⅳ</div> + <div class="otp-count-timer"> + {{emailOtpCounter}} + </div> + </el-row> + + <el-row> + <input + class="pam-input mt-10" + :class="{ + 'is-invalid': !emailOtpCode + }" + v-model="emailOtpCode" + placeholder="隢撓�撽�Ⅳ" + > + </el-row> + <div class="error mt-5 mb-10"> + <span v-show="emailCounterSec === 0">撽�Ⅳ撌脤�����撽�Ⅳ</span> + </div> + <el-button :disabled="!email || emailResendCounter !== 0 || !emailValid" icon="icon-arrow" @click="resentOtp('EMAIL')" > - ��撽�Ⅳ<span class="pam-field-title__hint pl-5">({{ emailResendCounter }})</span> + ��撽�Ⅳ<span + v-if="emailResendCounter !== 0" + class="pam-field-title__hint pl-5" + >({{ emailResendCounter }})</span> </el-button> - <div class="mt-10 smTxt_bold text--primary">! 隢�����mail敺�</div> </el-row> <el-row v-show="!showEmailVerifyField"> @@ -116,13 +148,12 @@ </div> - <el-row type="flex" justify="center" class="pam-login-page__action-bar mt-30"> + <el-row type="flex" justify="center" class="pam-login-page__action-bar mt-30 mb-30"> <el-button type="primary" - v-if="connectDevice === 'MOBILE' - && onPhoneVerifyStep === 'INPUT_OTP'" + v-if="(connectDevice === 'MOBILE' && onPhoneVerifyStep === 'INPUT_OTP') || (connectDevice === 'EMAIL' && onEmailVerifyResendStatus === 'CAN_RESEND')" :disabled="isSubmitBtnDisabled" - @click="phoneLogin"> + @click="login"> � </el-button> </el-row> @@ -291,7 +322,7 @@ <script lang="ts"> import { namespace } from 'nuxt-property-decorator'; import { Vue, Component, Ref } from 'vue-property-decorator'; -import { LoginRequest, loginVerify, OtpInfo, register, RegisterInfo, sendOtp } from '~/assets/ts/api/consultant'; +import { LoginRequest, LoginVerify, loginVerify, OtpInfo, register, RegisterInfo, sendOtp } from '~/assets/ts/api/consultant'; import { Role } from '~/assets/ts/models/enum/Role'; const roleStorage = namespace('localStorage'); @@ -307,18 +338,16 @@ phoneNumber = ''; otpCode = ''; onPhoneVerifyStep: 'APPLY_OTP' | 'INPUT_OTP' | 'SUBMIT_OTP' = 'APPLY_OTP'; - otpCounter = '15:00'; + otpCounterSec = 900; otpResendCounter = 30; otpInterval: any; phoneOtpInfo!: OtpInfo; - get isSubmitBtnDisabled(): boolean { - return !this.otpCode || !this.phoneNumber || !this.phoneValid; - } - email = ''; onEmailVerifyResendStatus: 'APPLY_OTP' | 'CAN_RESEND' = 'APPLY_OTP'; + emailCounterSec = 900; emailResendCounter = 30; + emailOtpCode = ''; emailResendInterval: any; emailOtpInfo!: OtpInfo; @@ -334,7 +363,20 @@ applyAccount_onAction = false; - detectContractReadStatus(event?: any): void { + mounted() { + const phoneOtpTime = localStorage.getItem('phoneOtpTime'); + const emailOtpTime = localStorage.getItem('emailOtpTime'); + const parsePhoneOtpTime = phoneOtpTime ? JSON.parse(phoneOtpTime) : ''; + const parseEmailOtpTime = emailOtpTime ? JSON.parse(emailOtpTime) : ''; + if (parsePhoneOtpTime && parsePhoneOtpTime.contactType === 'SMS') { + this.phoneDiffTime(parsePhoneOtpTime); + } + if (parseEmailOtpTime && parseEmailOtpTime.contactType === 'EMAIL') { + this.emailDiffTime(parseEmailOtpTime); + } + } + + detectContractReadStatus(event: any): void { const scrollTop = Math.round(event.target.scrollTop); const height = event.target.scrollHeight - event.target.clientHeight; if (Math.floor(scrollTop/10) === (Math.floor(height/10))) { @@ -342,12 +384,30 @@ } }; + get isSubmitBtnDisabled(): boolean { + return this.connectDevice === 'MOBILE' + ? (!this.otpCode || !this.phoneNumber || !this.phoneValid || !this.otpCounterSec) + : (!this.emailOtpCode || !this.email || !this.emailValid || !this.emailCounterSec) + } + + get phoneCounter() { + let min = Math.floor(this.otpCounterSec / 60); + let sec = Math.floor(this.otpCounterSec % 60); + return `${min < 10 ? '0' + min : min} : ${sec < 10 ? '0' + sec : sec}`; + } + + get emailOtpCounter() { + let min = Math.floor(this.emailCounterSec / 60); + let sec = Math.floor(this.emailCounterSec % 60); + return `${min < 10 ? '0' + min : min} : ${sec < 10 ? '0' + sec : sec}`; + } + get showPhoneOtpCodeField(): boolean { return this.connectDevice === 'MOBILE' && this.onPhoneVerifyStep === 'INPUT_OTP'; }; get showEmailVerifyField(): boolean { - return this.connectDevice === 'EMAIL' && this.onEmailVerifyResendStatus !== 'APPLY_OTP'; + return this.connectDevice === 'EMAIL' && this.onEmailVerifyResendStatus === 'CAN_RESEND'; }; get phoneValid() { @@ -360,6 +420,12 @@ return this.email ? rule.test(this.email) : true; } + get isLoginBtnDisabled() { + return this.connectDevice === 'MOBILE' + ? (!this.otpCode || !this.phoneNumber || !this.phoneValid || !this.otpCounterSec) + : (!this.emailOtpCode || !this.email || !this.emailValid || !this.emailCounterSec) + } + applyOtpVerification(type: string): void { const isMobile = this.connectDevice === 'MOBILE'; const loginInfo: LoginRequest = { @@ -368,7 +434,9 @@ } sendOtp(loginInfo).then(otpInfo => { if (otpInfo.success) { - this.startOtpCount(type, otpInfo); + this.storageOtpTime(type, otpInfo); + this.startOtpSetting(type); + this.startOtpCount(type); } }); }; @@ -377,52 +445,150 @@ if (type === 'MOBILE') { clearInterval(this.otpInterval); this.otpResendCounter = 30; - this.otpCounter = '15:00'; - this.startPhoneCounter(); + this.otpCounterSec = 900; } else { + clearInterval(this.emailResendInterval); this.emailResendCounter = 30; - this.startEmailCounter(); + this.emailCounterSec = 900; + } + this.applyOtpVerification(type); + } + + applyAccount(): void { + if (this.applyAccount_onAction) { + return ; + } + + this.applyAccount_onAction = true; + const registerInfo = this.setRegisterInfo(); + + register(registerInfo).then(res => { + this.storageIdToken(res.data.id_token); + this.storageRole(Role.USER); + this.storagePhoneOrEmail(registerInfo); + this.registerSuccessConfirmVisable = true; + }).catch(() => { + this.applyAccount_onAction = false; + }); + }; + + confirmApplySuccess(): void { + this.phoneSuccessConfirmVisable = false; + this.registerSuccessConfirmVisable = false; + this.$router.go(-1); + } + + login() { + const login: LoginVerify = this.setLoginInfo(); + this.removeOtpTime(); + loginVerify(login).then(res => { + this.storageIdToken(res.data.id_token); + this.storageRole(Role.USER); + this.phoneSuccessConfirmVisable = true; + this.storagePhoneOrEmail(this.setRegisterInfo()); + }).catch(error => { + if (error.response.status === 401) { + this.registerDialogVisible = true; + setTimeout(() => { + const isScrollBarNeedless = this.contract.scrollHeight <= this.contract.clientHeight; + if (isScrollBarNeedless) { + this.isReadContract = true; + } + }, 1000); + } + }) + } + + destroyed() { + this.removeOtpTime(); + clearInterval(this.otpInterval); + clearInterval(this.emailResendInterval); + } + + private phoneDiffTime(parseOtpTime: any) { + const diffSecs = this.calcDiffSecs(parseOtpTime.time); + + if (diffSecs < this.otpCounterSec) { + this.otpResendCounter = diffSecs < 30 ? 30 - diffSecs : 0; + this.otpCounterSec -= diffSecs; + this.phoneNumber = parseOtpTime.phone; + this.onPhoneVerifyStep = 'INPUT_OTP'; + this.phoneOtpInfo = this.setOtpInfo(parseOtpTime); + this.startOtpCount('MOBILE'); + } else { + localStorage.removeItem('phoneOtpTime'); + } + } + + private emailDiffTime(parseOtpTime: any) { + const diffSecs = this.calcDiffSecs(parseOtpTime.time); + + if (diffSecs < this.emailCounterSec) { + this.emailResendCounter = diffSecs < 30 ? 30 - diffSecs : 0; + this.emailCounterSec -= diffSecs; + this.email = parseOtpTime.email; + this.onEmailVerifyResendStatus = 'CAN_RESEND'; + this.emailOtpInfo = this.setOtpInfo(parseOtpTime); + this.startOtpCount('EMAIL'); + } else { + localStorage.removeItem('emailOtpTime'); + } + } + + private calcDiffSecs(parseOtpTime) { + const currentTime = new Date().getTime(); + const storageTime = new Date(parseOtpTime).getTime(); + return Math.floor((currentTime - storageTime) / 1000); + } + + private setOtpInfo(parseOtpTime) { + return { + indexKey: parseOtpTime.indexKey, + success: true, + failCode: '', + failReason: '', + } + } + + private storageOtpTime(type: string, otpInfo: OtpInfo) { + type === 'MOBILE' ? this.phoneOtpInfo = otpInfo : this.emailOtpInfo = otpInfo; + const info = {...this.setRegisterInfo(), time: new Date()} + type === 'MOBILE' ? localStorage.setItem('phoneOtpTime',JSON.stringify(info)) + : localStorage.setItem('emailOtpTime',JSON.stringify(info)); + } + + private startOtpSetting(type: string) { + if (type === 'MOBILE') { + this.onPhoneVerifyStep = 'INPUT_OTP'; + } else { + this.onEmailVerifyResendStatus = 'CAN_RESEND'; this.emailOtpConfirmVisable = true; } } - private startOtpCount(type: string, otpInfo) { - type === 'MOBILE' ? this.phoneOtpInfo = otpInfo : this.emailOtpInfo = otpInfo; - if (type === 'MOBILE') { - this.onPhoneVerifyStep = 'INPUT_OTP'; - this.startPhoneCounter(); - } else { - this.onEmailVerifyResendStatus = 'CAN_RESEND'; - this.startEmailCounter(); - this.emailOtpConfirmVisable = true; - } + private startOtpCount(type: string) { + type === 'MOBILE' ? this.startPhoneCounter() : this.startEmailCounter();; } private startEmailCounter() { this.emailResendInterval = setInterval(() => { - this.emailResendCounter -= 1; - if (this.emailResendCounter === 0) { - clearInterval(this.emailResendInterval) + this.emailCounterSec -= 1; + if (this.emailResendCounter !== 0) { + this.emailResendCounter -= 1; + } + if (this.emailCounterSec === 0) { + clearInterval(this.emailResendInterval); } }, 1000) } private startPhoneCounter() { - const minCount = this.otpCounter.split(':'); - let secCount = (+minCount[0] * 60) + (+minCount[1]); - let min = 0; - let sec = 0; this.otpInterval = setInterval(() => { - secCount -= 1; - min = Math.floor(secCount/60); - sec = Math.floor(secCount%60); - this.otpCounter = `${min < 10 ? '0' + min : min}:${sec < 10 ? '0' + sec : sec}`; - + this.otpCounterSec -= 1; if (this.otpResendCounter !== 0) { this.otpResendCounter -= 1; } - - if (secCount === 0) { + if (this.otpCounterSec === 0) { clearInterval(this.otpInterval) } }, 1000) @@ -446,93 +612,55 @@ } } - applyAccount(): void { - if (this.applyAccount_onAction) { - return ; + private storagePhoneOrEmail(registerInfo:RegisterInfo):void{ + const info = {...registerInfo, time: new Date()} + localStorage.setItem('userInfo',JSON.stringify(info)); + } + + private removeOtpTime() { + localStorage.removeItem('emailOtpTime'); + localStorage.removeItem('phoneOtpTime'); + } + + private setLoginInfo() { + const isMobile = this.connectDevice === 'MOBILE' + return { + account: isMobile ? this.phoneNumber : this.email, + indexKey: isMobile ? this.phoneOtpInfo.indexKey : this.emailOtpInfo.indexKey, + otpCode: isMobile ? this.otpCode : this.emailOtpCode } - - this.applyAccount_onAction = true; - const registerInfo = this.setRegisterInfo(); - this.storagePhoneOrEmail(registerInfo); - register(registerInfo).then(res => { - this.storageIdToken(res.data.id_token); - this.storageRole(Role.USER); - this.registerSuccessConfirmVisable = true; - }).catch(() => { - this.applyAccount_onAction = false; - }); - }; - - storagePhoneOrEmail(registerInfo:RegisterInfo):void{ - localStorage.setItem('userInfo',JSON.stringify(registerInfo)); } - - confirmApplySuccess(): void { - this.phoneSuccessConfirmVisable = false; - this.registerSuccessConfirmVisable = false; - this.$router.go(-1); - } - - phoneLogin() { - const login = { - account: this.phoneNumber, - indexKey: this.phoneOtpInfo.indexKey, - otpCode: this.otpCode - } - - loginVerify(login).then(res => { - this.storageIdToken(res.data.id_token); - this.storageRole(Role.USER); - this.phoneSuccessConfirmVisable = true; - }).catch(error => { - if (error.response.status === 401) { - this.registerDialogVisible = true; - setTimeout(() => { - const isScrollBarNeedless = this.contract.scrollHeight <= this.contract.clientHeight; - if (isScrollBarNeedless) { - this.isReadContract = true; - } - }, 1000); - } - }); - } - - destroyed() { - clearInterval(this.otpInterval); - clearInterval(this.emailResendInterval); - } - } </script> <style lang="scss"> .pam-login-page { - font-size: 20px !important; - display: flex; - flex-direction: column; - .pam-login-page__action-bar { + font-size: 20px !important; display: flex; - flex: 1; - align-items: flex-end; + flex-direction: column; + .pam-login-page__action-bar { + display: flex; + flex: 1; + align-items: flex-end; + } } -} -.pam-input { - height: 26px; - width: calc(100% - 36px); - border-radius: 10px !important; - padding: 12px 18px !important; - border:1px solid #CCCCCC; - outline: 0; - @extend .text--middle; - &::placeholder { - color: $PRUDENTIAL_GREY; + .pam-input { + height: 26px; + width: calc(100% - 36px); + border-radius: 10px !important; + padding: 12px 18px !important; + border:1px solid #CCCCCC; + outline: 0; + @extend .text--middle; + &::placeholder { + color: $PRUDENTIAL_GREY; + } + &.is-invalid { + border: 1px solid $PRIMARY_RED !important; + border-radius: 20px; + } } - &.is-invalid { - border: 1px solid $PRIMARY_RED !important; - border-radius: 20px; - } -} .pam-register-dialog__contract { $DEVICE_EXTRA_HEIGHT: 42px; @@ -544,64 +672,79 @@ border-radius: 6px; border: 1px solid #707070; padding: 20px; - max-height: 335px; -} - -.pam-radio { - color: $PRIMARY_RED; - align-items: center; - display: flex; - font-size: 20px; - font-weight: bold; - input { - display: none; - } - i { - font-size: 27px; - padding-right: 5px; + @include desktop { + height: 335px; } } -.pam-register-dialog { - padding: 30px 20px; - display: flex; - flex-direction: column; - border-radius: 0; - &.el-dialog { - border-radius: 0; + .pam-register-dialog__contract { + $DEVICE_EXTRA_HEIGHT: 42px; + $ALIGN_PADDING: 60px; + $TOP_CONTENT_HEIGHT: 186px; + $BOTTOM_CONTENT_HEIGHT: 131px; + max-height: calc(100vh - $DEVICE_EXTRA_HEIGHT - $ALIGN_PADDING - $TOP_CONTENT_HEIGHT - $BOTTOM_CONTENT_HEIGHT); + overflow-y: scroll; + border-radius: 6px; + border: 1px solid #707070; + padding: 20px; } - .el-dialog__header { - padding: 0; - margin-bottom: 30px; - .el-dialog__title { - @extend .subTitle; + + .pam-radio { + color: $PRIMARY_RED; + align-items: center; + display: flex; + font-size: 20px; + font-weight: bold; + input { + display: none; + } + i { + font-size: 27px; + padding-right: 5px; } } - .el-dialog__body { - flex: 1; - padding: 0; - margin-bottom: 30px; + + .pam-register-dialog { + padding: 30px 20px; + display: flex; + flex-direction: column; + border-radius: 0; + &.el-dialog { + border-radius: 0; + } + .el-dialog__header { + padding: 0; + margin-bottom: 30px; + .el-dialog__title { + @extend .subTitle; + } + } + .el-dialog__body { + flex: 1; + padding: 0; + margin-bottom: 30px; + } + .el-dialog__footer { + padding: 0 !important; + } } - .el-dialog__footer { - padding: 0 !important; + + .pam-field-title__hint { + @extend .smTxt_bold; + color: #68737A; } -} -.pam-field-title__hint { - @extend .smTxt_bold; - color: #68737A; -} + .error { + @extend .smTxt_bold; + @extend .text--primary; + height: 16px; + } -.error { - @extend .smTxt_bold; - @extend .text--primary; - height: 16px; -} - -.pam-popUp-title { - line-height: 24px; -} -.disabled { - color: #A7A8AA; -} + .pam-popUp-title { + font-size: 20px; + line-height: 27px; + } + .disabled { + color: #A7A8AA; + } </style> -- Gitblit v1.8.0