| | |
| | | <el-row type="flex" justify="space-between"> |
| | | <div class="mdTxt">輸å
¥é©è碼</div> |
| | | <div class="otp-count-timer"> |
| | | {{phoneCounter}} |
| | | {{counterTime(otpCounterSec)}} |
| | | </div> |
| | | </el-row> |
| | | |
| | |
| | | <el-row type="flex" justify="space-between"> |
| | | <div class="mdTxt">輸å
¥é©è碼</div> |
| | | <div class="otp-count-timer"> |
| | | {{emailOtpCounter}} |
| | | {{counterTime(emailCounterSec)}} |
| | | </div> |
| | | </el-row> |
| | | |
| | |
| | | :isOpen.sync="registerDialogVisible" |
| | | :dialogWidth="'90%'" |
| | | class="pam-register-dialog" |
| | | @closePopUp="isReadContract = false" |
| | | @closePopUp="isReadContract = false;agreeContract = false" |
| | | > |
| | | <div class="subTitle text--center mb-20">æ¡è¿æ°ä½¿ç¨è
</div> |
| | | <el-row> |
| | |
| | | import { RegisterInfo } from '~/shared/models/registerInfo'; |
| | | import loginService from '~/shared/services/login.service'; |
| | | import messageBoxService from '~/shared/services/message-box.service'; |
| | | import otpService, { OtpStorageName } from '~/shared/services/otp.service'; |
| | | |
| | | const roleStorage = namespace('localStorage'); |
| | | |
| | | @Component |
| | | export default class Login extends Vue { |
| | | @roleStorage.Mutation storageIdToken!: (token:string) => void; |
| | | @roleStorage.Mutation storageRole!: (role:string) => void; |
| | | @roleStorage.Mutation |
| | | storageIdToken!: (token:string) => void; |
| | | |
| | | @roleStorage.Mutation |
| | | storageRole!: (role:string) => void; |
| | | |
| | | @Ref('contract') readonly contract!: any; |
| | | |
| | | connectDevice: 'MOBILE' | 'EMAIL' = 'MOBILE'; |
| | |
| | | otpCounterSec = 300; |
| | | otpResendCounter = 30; |
| | | otpInterval: any; |
| | | phoneOtpInfo!: OtpInfo; |
| | | phoneOtpIndexKey!: string; |
| | | |
| | | email = ''; |
| | | onEmailVerifyResendStatus: 'APPLY_OTP' | 'CAN_RESEND' = 'APPLY_OTP'; |
| | |
| | | emailResendCounter = 30; |
| | | emailOtpCode = ''; |
| | | emailResendInterval: any; |
| | | emailOtpInfo!: OtpInfo; |
| | | emailOtpIndexKey!: string; |
| | | |
| | | autoRedirectCounter = 3; |
| | | autoRedirectInterval: any; |
| | |
| | | previousPath = ''; |
| | | |
| | | ///////////////////////////////////////////////////// |
| | | 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); |
| | | } |
| | | } |
| | | |
| | | beforeRouteEnter (to, from, next) { |
| | | next(vm => { |
| | | console.log(from.path, 'beforeRouteEnter'); |
| | | vm.previousPath = from.path; |
| | | }) |
| | | } |
| | | |
| | | mounted() { |
| | | this.parsePhoneOtpTimeFromStorage(); |
| | | this.parseEmailOtpTimeFromStorage(); |
| | | } |
| | | |
| | | private parsePhoneOtpTimeFromStorage() { |
| | | const parsePhoneOtpTime = otpService.parseOtpTime(OtpStorageName.PHONE); |
| | | const diffSecs = otpService.diffOtpTime(OtpStorageName.PHONE, this.otpCounterSec); |
| | | |
| | | if (parsePhoneOtpTime && diffSecs) { |
| | | this.otpResendCounter = diffSecs < 30 ? 30 - diffSecs : 0; |
| | | this.otpCounterSec -= diffSecs; |
| | | this.phoneNumber = parsePhoneOtpTime.phone ? parsePhoneOtpTime.phone : ''; |
| | | this.onPhoneVerifyStep = 'INPUT_OTP'; |
| | | this.phoneOtpIndexKey = parsePhoneOtpTime.indexKey; |
| | | this.startOtpCount('MOBILE'); |
| | | } |
| | | } |
| | | |
| | | private parseEmailOtpTimeFromStorage() { |
| | | const parseEmailOtpTime = otpService.parseOtpTime(OtpStorageName.EMAIL); |
| | | const diffSecs = otpService.diffOtpTime(OtpStorageName.EMAIL, this.emailCounterSec); |
| | | |
| | | if (parseEmailOtpTime && diffSecs) { |
| | | this.emailResendCounter = diffSecs < 30 ? 30 - diffSecs : 0; |
| | | this.emailCounterSec -= diffSecs; |
| | | this.email = parseEmailOtpTime.email ? parseEmailOtpTime.email : ''; |
| | | this.onEmailVerifyResendStatus = 'CAN_RESEND'; |
| | | this.emailOtpIndexKey = parseEmailOtpTime.indexKey; |
| | | this.startOtpCount('EMAIL'); |
| | | } |
| | | } |
| | | |
| | | destroyed() { |
| | |
| | | |
| | | ////////////////////////////////////////////////////////// |
| | | |
| | | 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))) { |
| | | this.isReadContract = true; |
| | | } |
| | | }; |
| | | |
| | | 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 === 'CAN_RESEND'; |
| | | }; |
| | | |
| | | get phoneValid() { |
| | | const rule = /^09[0-9]{8}$/; |
| | | return this.phoneNumber ? rule.test(this.phoneNumber) : true; |
| | | } |
| | | |
| | | get emailValid() { |
| | | const rule = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/; |
| | | return this.email ? rule.test(this.email) : true; |
| | | } |
| | | |
| | | applyOtpVerification(type: string): void { |
| | | const isMobile = this.connectDevice === 'MOBILE'; |
| | | const loginInfo: LoginRequest = { |
| | | loginType: isMobile ? 'SMS' : 'EMAIL', |
| | | account: isMobile ? this.phoneNumber : this.email, |
| | | } |
| | | loginService.sendOtp(loginInfo).then(otpInfo => { |
| | | if (otpInfo.success) { |
| | | this.storageOtpTime(type, otpInfo); |
| | | this.startOtpSetting(type); |
| | | this.startOtpCount(type); |
| | | } else { |
| | | const errorMsg = OtpErrorCode[otpInfo.failCode] ? OtpErrorCode[otpInfo.failCode]:'OTP系統é¯èª¤'; |
| | | messageBoxService.showErrorMessage(errorMsg); |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | resentOtp(type: string) { |
| | | this.resetOtpSetting(type); |
| | | this.applyOtpVerification(type); |
| | | } |
| | | |
| | | deleteOtpInfo(type: string) { |
| | | this.resetOtpSetting(type); |
| | | if (type === 'MOBILE') { |
| | | this.onPhoneVerifyStep = 'APPLY_OTP'; |
| | | this.phoneNumber = ''; |
| | | this.otpCode = ''; |
| | | } else { |
| | | this.onEmailVerifyResendStatus = 'APPLY_OTP'; |
| | | this.email = ''; |
| | | this.emailOtpCode = ''; |
| | | } |
| | | //////////////////// ç»å
¥ |
| | | login() { |
| | | const login: LoginVerify = this.setLoginInfo(); |
| | | this.removeOtpTime(); |
| | | loginService.loginVerify(login).then(res => { |
| | | this.storageIdToken(res.id_token); |
| | | this.storageRole(Role.USER); |
| | | this.phoneSuccessConfirmVisable = true; |
| | | this.autoRedirect(); |
| | | this.storagePhoneOrEmail(this.setRegisterInfo()); |
| | | }).catch(error => { |
| | | this.checkHttpErrorStatus(error); |
| | | }); |
| | | } |
| | | |
| | | confirmApplySuccess(): void { |
| | | this.phoneSuccessConfirmVisable = false; |
| | | this.registerSuccessConfirmVisable = false; |
| | | this.redirect(); |
| | | } |
| | | |
| | | //////////////////// 註å |
| | | applyAccount(): void { |
| | | if (this.applyAccount_onAction) { |
| | | return ; |
| | |
| | | }); |
| | | }; |
| | | |
| | | confirmApplySuccess(): void { |
| | | this.phoneSuccessConfirmVisable = false; |
| | | this.registerSuccessConfirmVisable = false; |
| | | this.redirect(); |
| | | } |
| | | |
| | | login() { |
| | | const login: LoginVerify = this.setLoginInfo(); |
| | | this.removeOtpTime(); |
| | | loginService.loginVerify(login).then(res => { |
| | | this.storageIdToken(res.id_token); |
| | | this.storageRole(Role.USER); |
| | | this.phoneSuccessConfirmVisable = true; |
| | | this.autoRedirect(); |
| | | this.storagePhoneOrEmail(this.setRegisterInfo()); |
| | | }).catch(error => { |
| | | this.checkHttpErrorStatus(error); |
| | | }); |
| | | } |
| | | |
| | | |
| | | ////////////////////////////////////////////////////////////////// |
| | | private checkHttpErrorStatus(error:any):void{ |
| | | switch (error.response.status) { |
| | | case 401: |
| | | const errorMsg = OtpErrorCode[error.response?.data?.detail] ? OtpErrorCode[error.response?.data?.detail]:'OTP系統é¯èª¤'; |
| | | messageBoxService.showErrorMessage(errorMsg); |
| | | break; |
| | | case 403: |
| | | this.registerDialogVisible = true; |
| | | setTimeout(() => { |
| | | const isScrollBarNeedless = this.contract.scrollHeight <= this.contract.clientHeight; |
| | | if (isScrollBarNeedless) { |
| | | this.isReadContract = true; |
| | | } |
| | | }, 1000); |
| | | break; |
| | | default: |
| | | messageBoxService.showErrorMessage('',error); |
| | | break; |
| | | } |
| | | } |
| | | |
| | | private autoRedirect() { |
| | | this.autoRedirectInterval = setInterval(() => { |
| | | this.autoRedirectCounter -= 1; |
| | |
| | | find > -1 ? this.$router.go(-1) : this.$router.push('/'); |
| | | } |
| | | |
| | | 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'); |
| | | 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))) { |
| | | this.isReadContract = true; |
| | | } |
| | | } |
| | | }; |
| | | |
| | | 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'); |
| | | applyOtpVerification(type: string): void { |
| | | const isMobile = this.connectDevice === 'MOBILE'; |
| | | const loginInfo: LoginRequest = { |
| | | loginType: isMobile ? 'SMS' : 'EMAIL', |
| | | account: isMobile ? this.phoneNumber : this.email, |
| | | } |
| | | } |
| | | |
| | | private calcDiffSecs(parseOtpTime) { |
| | | const currentTime = new Date().getTime(); |
| | | const storageTime = new Date(parseOtpTime).getTime(); |
| | | return Math.floor((currentTime - storageTime) / 1000); |
| | | } |
| | | |
| | | private resetOtpSetting(type: string) { |
| | | if (type === 'MOBILE') { |
| | | clearInterval(this.otpInterval); |
| | | this.otpResendCounter = 30; |
| | | this.otpCounterSec = 300; |
| | | } else { |
| | | clearInterval(this.emailResendInterval); |
| | | this.emailResendCounter = 30; |
| | | this.emailCounterSec = 300; |
| | | } |
| | | } |
| | | |
| | | private setOtpInfo(parseOtpTime) { |
| | | return { |
| | | indexKey: parseOtpTime.indexKey, |
| | | success: true, |
| | | failCode: '', |
| | | failReason: '', |
| | | } |
| | | } |
| | | loginService.sendOtp(loginInfo).then(otpInfo => { |
| | | if (otpInfo.success) { |
| | | this.storageOtpTime(type, otpInfo); |
| | | this.startOtpSetting(type); |
| | | this.startOtpCount(type); |
| | | } else { |
| | | const errorMsg = OtpErrorCode[otpInfo.failCode] ? OtpErrorCode[otpInfo.failCode]:'OTP系統é¯èª¤'; |
| | | messageBoxService.showErrorMessage(errorMsg); |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | private storageOtpTime(type: string, otpInfo: OtpInfo) { |
| | | type === 'MOBILE' ? this.phoneOtpInfo = otpInfo : this.emailOtpInfo = otpInfo; |
| | | type === 'MOBILE' ? this.phoneOtpIndexKey = otpInfo.indexKey : this.emailOtpIndexKey = otpInfo.indexKey; |
| | | const info = {...this.setRegisterInfo(), time: new Date()} |
| | | type === 'MOBILE' ? localStorage.setItem('phoneOtpTime',JSON.stringify(info)) |
| | | : localStorage.setItem('emailOtpTime',JSON.stringify(info)); |
| | | const storageName = type === 'MOBILE' ? OtpStorageName.PHONE : OtpStorageName.EMAIL; |
| | | otpService.setOtpTimeToStorage(storageName, info); |
| | | } |
| | | |
| | | private startOtpSetting(type: string) { |
| | |
| | | }, 1000) |
| | | } |
| | | |
| | | private setRegisterInfo(): RegisterInfo { |
| | | return this.connectDevice === 'MOBILE' |
| | | ? { |
| | | phone: this.phoneNumber, |
| | | indexKey: this.phoneOtpInfo.indexKey, |
| | | otpCode: this.otpCode, |
| | | name: this.name, |
| | | contactType: 'SMS' |
| | | } |
| | | : { |
| | | email: this.email, |
| | | indexKey: this.emailOtpInfo.indexKey, |
| | | otpCode: this.otpCode, |
| | | name: this.name, |
| | | contactType: 'EMAIL' |
| | | } |
| | | resentOtp(type: string) { |
| | | this.resetOtpSetting(type); |
| | | this.applyOtpVerification(type); |
| | | } |
| | | |
| | | deleteOtpInfo(type: string) { |
| | | this.resetOtpSetting(type); |
| | | if (type === 'MOBILE') { |
| | | this.onPhoneVerifyStep = 'APPLY_OTP'; |
| | | this.phoneNumber = ''; |
| | | this.otpCode = ''; |
| | | } else { |
| | | this.onEmailVerifyResendStatus = 'APPLY_OTP'; |
| | | this.email = ''; |
| | | this.emailOtpCode = ''; |
| | | } |
| | | this.removeOtpTime(); |
| | | } |
| | | |
| | | private resetOtpSetting(type: string) { |
| | | if (type === 'MOBILE') { |
| | | clearInterval(this.otpInterval); |
| | | this.otpResendCounter = 30; |
| | | this.otpCounterSec = 300; |
| | | } else { |
| | | clearInterval(this.emailResendInterval); |
| | | this.emailResendCounter = 30; |
| | | this.emailCounterSec = 300; |
| | | } |
| | | } |
| | | |
| | | counterTime(counterSec) { |
| | | let min = Math.floor(counterSec / 60); |
| | | let sec = Math.floor(counterSec % 60); |
| | | return `${min < 10 ? '0' + min : min}:${sec < 10 ? '0' + sec : sec}`; |
| | | } |
| | | |
| | | ////////////////////////////////////////////////////////////////// |
| | | |
| | | private checkHttpErrorStatus(error:any):void{ |
| | | switch (error.response.status) { |
| | | case 401: |
| | | const errorMsg = OtpErrorCode[error.response?.data?.detail] ? OtpErrorCode[error.response?.data?.detail]:'OTP系統é¯èª¤'; |
| | | messageBoxService.showErrorMessage(errorMsg); |
| | | break; |
| | | case 403: |
| | | this.registerDialogVisible = true; |
| | | setTimeout(() => { |
| | | const isScrollBarNeedless = this.contract.scrollHeight <= this.contract.clientHeight; |
| | | if (isScrollBarNeedless) { |
| | | this.isReadContract = true; |
| | | } |
| | | }, 1000); |
| | | break; |
| | | default: |
| | | messageBoxService.showErrorMessage('',error); |
| | | break; |
| | | } |
| | | } |
| | | |
| | | private storagePhoneOrEmail(registerInfo:RegisterInfo):void{ |
| | |
| | | } |
| | | |
| | | private removeOtpTime() { |
| | | localStorage.removeItem('emailOtpTime'); |
| | | localStorage.removeItem('phoneOtpTime'); |
| | | otpService.removeOtpTimeToStorage(OtpStorageName.PHONE); |
| | | otpService.removeOtpTimeToStorage(OtpStorageName.EMAIL); |
| | | } |
| | | |
| | | |
| | | private setLoginInfo() { |
| | | const isMobile = this.connectDevice === 'MOBILE' |
| | | return { |
| | | account: isMobile ? this.phoneNumber : this.email, |
| | | indexKey: isMobile ? this.phoneOtpInfo.indexKey : this.emailOtpInfo.indexKey, |
| | | indexKey: isMobile ? this.phoneOtpIndexKey : this.emailOtpIndexKey, |
| | | otpCode: isMobile ? this.otpCode : this.emailOtpCode |
| | | } |
| | | } |
| | | |
| | | private setRegisterInfo(): RegisterInfo { |
| | | return this.connectDevice === 'MOBILE' |
| | | ? { |
| | | phone: this.phoneNumber, |
| | | indexKey: this.phoneOtpIndexKey, |
| | | otpCode: this.otpCode, |
| | | name: this.name, |
| | | contactType: 'SMS' |
| | | } |
| | | : { |
| | | email: this.email, |
| | | indexKey: this.emailOtpIndexKey, |
| | | otpCode: this.emailOtpCode, |
| | | name: this.name, |
| | | contactType: 'EMAIL' |
| | | } |
| | | } |
| | | |
| | | get isSubmitBtnDisabled(): boolean { |
| | | return this.connectDevice === 'MOBILE' |
| | | ? (!this.otpCode || !this.phoneNumber || !this.phoneValid || !this.otpCounterSec) |
| | | : (!this.emailOtpCode || !this.email || !this.emailValid || !this.emailCounterSec) |
| | | } |
| | | |
| | | get showPhoneOtpCodeField(): boolean { |
| | | return this.connectDevice === 'MOBILE' && this.onPhoneVerifyStep === 'INPUT_OTP'; |
| | | }; |
| | | |
| | | get showEmailVerifyField(): boolean { |
| | | return this.connectDevice === 'EMAIL' && this.onEmailVerifyResendStatus === 'CAN_RESEND'; |
| | | }; |
| | | |
| | | get phoneValid() { |
| | | const rule = /^09[0-9]{8}$/; |
| | | return this.phoneNumber ? rule.test(this.phoneNumber) : true; |
| | | } |
| | | |
| | | get emailValid() { |
| | | const rule = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/; |
| | | return this.email ? rule.test(this.email) : true; |
| | | } |
| | | } |
| | | </script> |
| | | |