| | |
| | | <div class="password-reset" @click="resetPassword">忘記密碼</div> |
| | | </div> |
| | | <div class="position-r mt-10"> |
| | | <input :type="checkPasswordType ? 'text' : 'password'" |
| | | <input :type="checkInputType ? 'text' : 'password'" |
| | | v-model="consultantDto.password" |
| | | :disabled="onOTPVerifyStep === 'CAN_RESEND'" |
| | | class="pam-consultant-login__input" |
| | |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- --> |
| | | <!-- OTP 驗證碼 --> |
| | | <div v-show="onOTPVerifyStep === 'CAN_RESEND'"> |
| | | <el-row type="flex" justify="space-between"> |
| | | <div class="mdTxt">輸入 OTP 驗證碼</div> |
| | |
| | | {{counterTime(otpCounterSec)}} |
| | | </div> |
| | | </el-row> |
| | | |
| | | <el-row> |
| | | <input |
| | | class="pam-consultant-login__input mt-10" |
| | |
| | | <div class="error mt-5 mb-10"> |
| | | <span v-show="otpCounterSec === 0">OTP 驗證碼已過期,請重發 OTP 驗證碼</span> |
| | | </div> |
| | | |
| | | <el-row> |
| | | <el-button |
| | | :disabled="!consultantDto.password || otpResendCounter !== 0 || !consultantDto.username" |
| | |
| | | v-if="otpResendCounter !== 0" |
| | | >({{ otpResendCounter }})</span> |
| | | </el-button> |
| | | |
| | | </el-row> |
| | | </div> |
| | | <div class="pam-paragraph"> |
| | | <el-button v-if="onOTPVerifyStep === 'APPLY_OTP'" icon="icon-arrow" |
| | | :disabled="!consultantDto.username || !consultantDto.password || verificationCode.length !== 4" |
| | | @click="applyOtpVerification"> |
| | | 發送 OTP 驗證碼</el-button> |
| | | </div> |
| | | <div class="pam-consultant-login__confirmBlock pam-paragraph" v-if="onOTPVerifyStep === 'CAN_RESEND'"> |
| | | <div class="pam-consultant-login__confirmBlock pam-paragraph"> |
| | | <button class="pam-consultant-login__confirm cursor--pointer fix-chrome-click--issue" |
| | | :disabled="!consultantDto.username || !consultantDto.password || !otpCode || !otpCounterSec" |
| | | :disabled="isSentBtnDisabled" |
| | | @click="sendInfo">送出</button> |
| | | </div> |
| | | </div> |
| | |
| | | :isOpen.sync="otpConfirmVisible" |
| | | > |
| | | <div class="pam-popUp-title text--center">已將驗證訊息發送至</div> |
| | | <div class="pam-popUp-title text--center">{{'email'}}</div> |
| | | <div class="pam-popUp-title text--center">請查看電子郵件並完成驗證流程</div> |
| | | <div class="pam-popUp-title text--center">簡訊或email</div> |
| | | <div class="pam-popUp-title text--center">請查看手機訊息或電子郵件並完成驗證流程</div> |
| | | <div class="pam-popUp-confirm-bolck mt-30"> |
| | | <div class="text--center"> |
| | | <el-button |
| | |
| | | import messageBoxService from '~/shared/services/message-box.service'; |
| | | import loginService from '~/shared/services/login.service' |
| | | import { AgentInfo } from '~/shared/models/agent-info.model'; |
| | | import { OtpErrorCode } from '~/shared/models/enum/otpErrorCode'; |
| | | |
| | | const loginStore = namespace('login.store'); |
| | | const roleStorage = namespace('localStorage'); |
| | |
| | | otpConfirmVisible = false; |
| | | otpCode = ''; |
| | | onOTPVerifyStep: 'APPLY_OTP' | 'CAN_RESEND' = 'APPLY_OTP'; |
| | | otpCounterSec = 50; |
| | | otpCounterSec = 300; |
| | | otpResendCounter = 30; |
| | | otpInterval: NodeJS.Timeout | null = null; |
| | | otpIndexKey!: string; |
| | |
| | | this.storeUserName(); |
| | | } |
| | | |
| | | public applyOtpVerification(type: string): void { |
| | | // TODO: sendOTP |
| | | const otpInfo = { |
| | | indexKey: "string", /** 用於帶入otp認證時 */ |
| | | success: true, /** Otp是否有成功發送 */ |
| | | failCode: "string", |
| | | failReason: "string", |
| | | } |
| | | if (otpInfo.success) { |
| | | // this.storageOtpTime(type, otpInfo); |
| | | this.startOtpSetting(type); |
| | | this.startOtpCount(); |
| | | } else { |
| | | // TODO: otp error |
| | | // const errorMsg = OtpErrorCode[otpInfo.failCode] ? OtpErrorCode[otpInfo.failCode]:'OTP系統錯誤'; |
| | | // messageBoxService.showErrorMessage(errorMsg); |
| | | } |
| | | } |
| | | |
| | | public sendInfo():void{ |
| | | if (this.onOTPVerifyStep === 'APPLY_OTP') { |
| | | this.isAlreadyDone |
| | | ? this.verify() |
| | | : messageBoxService.showErrorMessage('請確認帳號、密碼以及驗證碼是否填寫完畢'); |
| | | } else { |
| | | this.login(); |
| | | } |
| | | |
| | | get isAlreadyDone():boolean{ |
| | | return !!(this.verificationCode && this.consultantDto.username && this.consultantDto.password); |
| | | } |
| | | |
| | | resetPassword() { |
| | |
| | | resetOtpSetting() { |
| | | clearInterval(this.otpInterval ?? undefined); |
| | | this.otpResendCounter = 30; |
| | | this.otpCounterSec = 50; |
| | | this.otpCounterSec = 300; |
| | | this.onOTPVerifyStep = 'APPLY_OTP'; |
| | | this.otpCode = ''; |
| | | } |
| | |
| | | this.otpCode = ''; |
| | | } |
| | | |
| | | get checkPasswordType(): boolean { |
| | | get isAlreadyDone():boolean{ |
| | | return !!(this.verificationCode && this.consultantDto.username && this.consultantDto.password); |
| | | } |
| | | |
| | | get checkInputType(): boolean { |
| | | return this.onOTPVerifyStep === 'CAN_RESEND' ? false : this.isShowPassword; |
| | | } |
| | | |
| | | get isSentBtnDisabled(): boolean { |
| | | if (this.onOTPVerifyStep === 'APPLY_OTP') { |
| | | return !this.consultantDto.username || !this.consultantDto.password || this.verificationCode.length !== 4; |
| | | } else { |
| | | return !this.consultantDto.username || !this.consultantDto.password || !this.otpCode || !this.otpCounterSec; |
| | | } |
| | | } |
| | | |
| | | //////////////////////////////////////////////////////////////////// |
| | | |
| | | private verify():void{ |
| | |
| | | |
| | | private loginWithConsultant(): void { |
| | | loginService.logInToConsultant(this.consultantDto, this.verificationCode).then(res => { |
| | | this.getLoginConsultantDetail(this.consultantDto.username); |
| | | this.storageIdToken(res.data.id_token); |
| | | this.storageRole(Role.ADMIN); |
| | | this.storageConsultantId(this.consultantDto.username) |
| | | this.storeUserName(); |
| | | this.$router.push('/myAppointmentList/appointmentList'); |
| | | this.applyOtpVerification(); |
| | | }).catch((error:AxiosError)=>{ |
| | | this.checkHttpErrorStatus(error); |
| | | }); |
| | | } |
| | | |
| | | private checkHttpErrorStatus(error:any):void{ |
| | | this.clearValue(); |
| | | this.onOTPVerifyStep = 'APPLY_OTP'; |
| | | this.regenerateImgOfVerification(); |
| | | switch (error.response.status) { |
| | | case 401: |
| | |
| | | this.verificationCode = ''; |
| | | } |
| | | |
| | | private startOtpSetting(type: string) { |
| | | //////////////////// 發送/重發驗證碼 |
| | | private applyOtpVerification(): void { |
| | | loginService.sentOtpWithConsultant(this.consultantDto.username).then(otpInfo => { |
| | | if (otpInfo.success) { |
| | | this.otpIndexKey = otpInfo.indexKey; |
| | | this.startOtpSetting(); |
| | | this.startOtpCount(); |
| | | } else { |
| | | const errorMsg = OtpErrorCode[otpInfo.failCode] ? OtpErrorCode[otpInfo.failCode]:'OTP系統錯誤'; |
| | | messageBoxService.showErrorMessage(errorMsg); |
| | | } |
| | | }) |
| | | } |
| | | |
| | | private startOtpSetting() { |
| | | this.onOTPVerifyStep = 'CAN_RESEND'; |
| | | this.otpConfirmVisible = true; |
| | | } |
| | |
| | | this.otpCounterSec -= 1; |
| | | if (this.otpResendCounter !== 0) { |
| | | this.otpResendCounter -= 1; |
| | | if (this.otpResendCounter === 0) { |
| | | // this.regenerateImgOfVerification(); |
| | | } |
| | | } |
| | | if (this.otpCounterSec === 0 && this.otpInterval) { |
| | | clearInterval(this.otpInterval); |
| | | } |
| | | }, 1000) |
| | | } |
| | | |
| | | private login() { |
| | | const loginVerify = { |
| | | account: this.consultantDto.username, |
| | | indexKey: this.otpIndexKey, |
| | | otpCode: this.otpCode |
| | | } |
| | | loginService.loginVerifyWithConsultant(loginVerify).then(res => { |
| | | this.getLoginConsultantDetail(this.consultantDto.username); |
| | | this.storageIdToken(res.id_token); |
| | | this.storageRole(Role.ADMIN); |
| | | this.storageConsultantId(this.consultantDto.username) |
| | | this.storeUserName(); |
| | | this.$router.push('/myAppointmentList/appointmentList'); |
| | | }) |
| | | } |
| | | }; |
| | | </script> |
| | | |