保誠-保戶業務員媒合平台
wayne
2022-01-26 6fa4bba623713c396432ba8b863846883d6a1906
PAMapp/pages/login/index.vue
@@ -1,116 +1,179 @@
<template>
    <div class="pam-login-page">
      <div class="text--middle">登入</div>
        <div class='mb-30'>
          <div class="mdTxt">登入 | 註冊方式</div>
          <div class="pam-field-title__hint mt-5 mb-10"
          >顧問將會以此{{connectDevice === 'MOBILE' ? '手機號碼' : 'Email'}}為主要預約諮詢聯繫方式</div>
      <div class="pam-paragraph">
        <div class="mdTxt">
        綁定方式
        </div>
        <div class="pam-tags">
          <el-row type="flex" class="pt-10">
            <el-button
              :class="{ 'active': connectDevice === 'MOBILE'}"
              @click="connectDevice = 'MOBILE'">手機號碼</el-button>
            <el-button
              :class="{ 'active': connectDevice === 'EMAIL'}"
              @click="connectDevice = 'EMAIL'">Email</el-button>
          </el-row>
        </div>
          <el-row type="flex" class="pt-10" v-show="connectDevice === 'MOBILE'">
            <input
              class="pam-input"
              :class="{
                'is-invalid': !phoneNumber
              }"
              v-model="phoneNumber"
              placeholder="請輸入手機號碼"
              >
          </el-row>
          <el-row class="pt-10" v-show="connectDevice === 'EMAIL'">
            <input
              class="pam-input"
              :class="{
                'is-invalid': !phoneNumber
              }"
              v-model="email"
              placeholder="請輸入 Email 地址"
              >
          </el-row>
          <div class="pt-30" v-show="showPhoneOtpCodeField">
            <el-row type="flex" justify="space-between">
                <div class="mdTxt">輸入驗證碼</div>
                <div class="otp-count-timer">
                  13:50
                </div>
          <div class="pam-tags">
            <el-row type="flex" class="pt-30">
              <el-button
                :class="{ 'active': connectDevice === 'MOBILE'}"
                @click="connectDevice = 'MOBILE'">手機號碼</el-button>
              <el-button
                :class="{ 'active': connectDevice === 'EMAIL'}"
                @click="connectDevice = 'EMAIL'">Email</el-button>
            </el-row>
          </div>
            <el-row class="pt-10">
          <div class="pam-inputs mb-10">
            <div class="pam-input-position pt-10" v-show="connectDevice === 'MOBILE'">
              <input
                  class="pam-input"
                  :class="{
                    'is-invalid': !phoneValid
                  }"
                  v-model="phoneNumber"
                  placeholder="請輸入手機號碼"
                  :disabled="showPhoneOtpCodeField"
                >
              <i
                class="icon-close"
                v-if="onPhoneVerifyStep !== 'APPLY_OTP'"
                @click="deleteOtpInfo('MOBILE')"
              ></i>
              <div class="error mt-5 mb-5">
                  <span v-show="!phoneValid">手機號碼格式有誤</span>
              </div>
            </div>
            <div class="pam-input-position pt-10" v-show="connectDevice === 'EMAIL'">
              <input
                class="pam-input"
                :class="{
                  'is-invalid': !otpCode
                  'is-invalid': !emailValid
                }"
                v-model="otpCode"
                placeholder="請輸入驗證碼"
                v-model="email"
                placeholder="請輸入 Email 地址"
                :disabled="showEmailVerifyField"
              >
              <i
                class="icon-close"
                v-if="showEmailVerifyField"
                @click="deleteOtpInfo('EMAIL')"
              ></i>
              <div class="error mt-5 mb-5">
                  <span v-show="!emailValid">Email格式有誤</span>
              </div>
            </div>
          </div>
          <!-- mobile 驗證碼 -->
          <template v-if="connectDevice === 'MOBILE'">
            <div v-show="showPhoneOtpCodeField">
              <el-row type="flex" justify="space-between">
                  <div class="mdTxt">輸入驗證碼</div>
                  <div class="otp-count-timer">
                    {{counterTime(otpCounterSec)}}
                  </div>
              </el-row>
              <el-row>
                <input
                  class="pam-input mt-10"
                  :class="{
                    'is-invalid': !otpCode
                  }"
                  v-model="otpCode"
                  placeholder="請輸入驗證碼"
                  >
              </el-row>
              <div class="error mt-5 mb-10">
                  <span v-show="otpCounterSec === 0">驗證碼已過期,請重發驗證碼</span>
              </div>
              <el-row>
                <el-button
                  :disabled="!phoneNumber || otpResendCounter !== 0 || !phoneValid"
                  @click="resentOtp('MOBILE')"
                  icon="icon-arrow"
                >
                  重發驗證碼<span
                    class="pam-field-title__hint pl-5"
                    v-if="otpResendCounter !== 0"
                  >({{ otpResendCounter }})</span>
                </el-button>
              </el-row>
            </div>
            <el-row>
              <el-button
                  v-if="onPhoneVerifyStep === 'APPLY_OTP'"
                  :disabled="!phoneNumber || !phoneValid"
                  @click="applyOtpVerification('MOBILE')"
                  icon="icon-arrow"
                >
                  發送驗證碼
                </el-button>
            </el-row>
            <el-row class="pt-10">
              <button
                class="pam-otp-resend-btn"
                :class="{'disabled': true}">
                <i class="icon-arrow"></i>
                重發驗證碼({{ otpResendCounter }})
              </button>
            </el-row>
          </div>
          </template>
          <div v-show="showEmailVerifyField">
            <el-row class="pt-10">
              <button
                class="pam-otp-resend-btn"
                :class="{'disabled': onEmailVerifyResendStatus === 'CANNOT_RESEND'}">
                <i class="icon-arrow"></i>
                重發驗證碼({{ emailResendCounter }})
              </button>
          <!-- 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">
                    {{counterTime(emailCounterSec)}}
                  </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
                    v-if="emailResendCounter !== 0"
                    class="pam-field-title__hint pl-5"
                  >({{ emailResendCounter }})</span>
              </el-button>
            </el-row>
          </div>
            <el-row v-show="!showEmailVerifyField">
              <el-button
                  :disabled="!email || !emailValid"
                  @click="applyOtpVerification('EMAIL')"
                  icon="icon-arrow"
                >
                  發送驗證碼
                </el-button>
            </el-row>
          </template>
      </div>
      <el-row type="flex" justify="center" class="pam-login-page__action-bar">
        <div v-if="connectDevice === 'MOBILE'">
          <el-button
            type="primary"
            v-if="onPhoneVerifyStep === 'APPLY_OTP'"
            :disabled="!phoneNumber"
            @click="applyOtpVerification">
            發送驗證碼
          </el-button>
          <el-button
            type="primary"
            v-if="connectDevice === 'MOBILE' && onPhoneVerifyStep === 'INPUT_OTP'"
            :disabled="!otpCode"
            @click="registerDialogVisable = true">
            送出
          </el-button>
        </div>
      <el-row type="flex" justify="center" class="pam-login-page__action-bar mt-30">
        <el-button
          type="primary"
          v-if="(connectDevice === 'MOBILE' && onPhoneVerifyStep === 'INPUT_OTP') || (connectDevice === 'EMAIL' && onEmailVerifyResendStatus === 'CAN_RESEND')"
          :disabled="isSubmitBtnDisabled"
          @click="login">
          送出
        </el-button>
      </el-row>
      <el-dialog
        title="歡迎新使用者"
        :custom-class="'pam-register-dialog'"
        :visible.sync="registerDialogVisable"
        :fullscreen="true"
        :close-on-click-modal="false"
        :show-close="false"
        center>
        <span>
      <PopUpFrame
        :isOpen.sync="registerDialogVisible"
        :dialogWidth="'90%'"
        class="pam-register-dialog"
        @closePopUp="isReadContract = false;agreeContract = false"
      >
          <div class="subTitle text--center mb-20">歡迎新使用者</div>
          <el-row>
            <input
              class="pam-input"
@@ -128,12 +191,13 @@
          </el-row>
          <el-row class="pt-10">
            <div
              v-if="registerDialogVisible"
              class="mdTxt pam-register-dialog__contract"
              @scroll="detectContructReadStatus">
              ref="contract"
              @scroll="detectContractReadStatus">
              <h3>蒐集個人資料告知事項</h3>
              <p class="mt-10">
              遵守個人資料保護法規定,在您提供個人資料予本處前,依法告
              知下列事項:
              遵守個人資料保護法規定,在您提供個人資料予本處前,依法告知下列事項:
              <p>
              <p class="mt-10">
@@ -152,13 +216,11 @@
              </p>
              <p class="mt-10">
              四、除蒐集之目的涉及國際業務或活動外,本處僅於中華民國領域內利用您的個人資
              料。
              四、除蒐集之目的涉及國際業務或活動外,本處僅於中華民國領域內利用您的個人資料。
              </p>
              <p class="mt-10">
              五、本處將於原蒐集之特定目的、本次以外之產業之推廣、宣導及輔導、以及其他公
              務機關請求行政協助之目的範圍內,合理利用您的個人資料。
              五、本處將於原蒐集之特定目的、本次以外之產業之推廣、宣導及輔導、以及其他公務機關請求行政協助之目的範圍內,合理利用您的個人資料。
              </p>
              <p class="mt-10">
@@ -192,183 +254,546 @@
          </el-row>
          <el-row class="pt-30">
            <div class="pam-agree-radio">
              <label for="agreeControct" class="pam-radio">
              <label for="agreeContract" class="pam-radio"
                :class="{disabled: !isReadContract}">
                <input
                  type="radio"
                  id="agreeControct"
                  @click="agreeControct = !agreeControct"
                  value="agreeControct">
                  <i :class="agreeControct ?'icon-checkbox-1': 'icon-checkbox'"></i>我同意並繼續
                  id="agreeContract"
                  @click="agreeContract = !agreeContract"
                  :disabled="!isReadContract"
                  value="agreeContract">
                  <i :class="agreeContract ?'icon-checkbox-1': 'icon-checkbox'"></i>我同意並繼續
              </label>
            </div>
          </el-row>
        </span>
        <span slot="footer" class="dialog-footer">
          <el-button
            type="primary"
            :disabled="!name || !agreeControct || !isReadContract"
            @click="applyAccount"
            >建立新帳號
          </el-button>
        </span>
      </el-dialog>
          <div class="text--center mt-10">
            <el-button
              type="primary"
              :disabled="!name || !agreeContract || !isReadContract"
              @click="applyAccount"
              >建立新帳號
            </el-button>
          </div>
      </PopUpFrame>
      <PopUpFrame class="pam-popUpFrame"
        :isOpen.sync="emailOtpConfirmVisable"
      >
        <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
                type="primary"
                @click="emailOtpConfirmVisable = false"
            >我知道了</el-button>
          </div>
        </div>
      </PopUpFrame>
      <PopUpFrame class="pam-popUpFrame"
        :isOpen.sync="registerSuccessConfirmVisable"
        @closePopUp="confirmApplySuccess"
      >
          <div class="pam-popUp-title text--center">
            歡迎您登入成功,如您預約諮詢,顧問會以您留下的{{ connectDevice === 'MOBILE' ? '手機號碼' : 'Email'}}與您聯繫
          </div>
          <div class="pam-popUp-txt text--center mb-10 mt-5"
          >即將轉跳頁面...{{autoRedirectCounter}}秒</div>
          <div class="pam-popUp-confirm-bolck mt-30">
            <div class="text--center">
              <el-button
                  type="primary"
                  @click="registerSuccessConfirmVisable = false"
              >我知道了</el-button>
            </div>
          </div>
      </PopUpFrame>
      <el-button class="mt-30" @click="fakeLogin">客戶登入</el-button>
      <PopUpFrame class="pam-popUpFrame"
        :isOpen.sync="phoneSuccessConfirmVisable"
        @closePopUp="confirmApplySuccess"
      >
          <div class="pam-popUp-title text--center"
          >歡迎您登入成功</div>
          <div class="pam-popUp-txt text--center mb-30 mt-5 xsTxt"
          >即將轉跳頁面...{{autoRedirectCounter}}秒</div>
          <div class="pam-popUp-confirm-bolck mt-30">
            <div class="text--center">
              <el-button
                  type="primary"
                  @click="phoneSuccessConfirmVisable = false"
              >我知道了</el-button>
            </div>
          </div>
      </PopUpFrame>
    </div>
</template>
<script lang="ts">
import { Vue, Component } from 'vue-property-decorator';
import { login } from '~/assets/ts/api/consultant';
import { Role } from '../../components/NavBar.vue';
import { namespace } from 'nuxt-property-decorator';
import { Vue, Component, Ref } from 'vue-property-decorator';
import { OtpErrorCode } from '~/shared/models/enum/otpErrorCode';
import { Role } from '~/shared/models/enum/Role';
import { LoginRequest } from '~/shared/models/loginRequest.model';
import { LoginVerify } from '~/shared/models/loginVerify.model';
import { OtpInfo } from '~/shared/models/otpInfo.model';
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;
  @Ref('contract') readonly contract!: any;
  connectDevice: 'MOBILE' | 'EMAIL' = 'MOBILE';
  phoneNumber = '';
  otpCode = '';
  onPhoneVerifyStep: 'APPLY_OTP' | 'INPUT_OTP' | 'SUBMIT_OTP' = 'APPLY_OTP';
  otpCounterSec = 300;
  otpResendCounter = 30;
  otpInterval: any;
  phoneOtpIndexKey!: string;
  email = '';
  onEmailVerifyResendStatus: 'CAN_RESEND' | 'CANNOT_RESEND' = 'CANNOT_RESEND';
  onEmailVerifyResendStatus: 'APPLY_OTP' | 'CAN_RESEND' = 'APPLY_OTP';
  emailCounterSec = 300;
  emailResendCounter = 30;
  emailOtpCode = '';
  emailResendInterval: any;
  emailOtpIndexKey!: string;
  registerDialogVisable = false;
  autoRedirectCounter = 3;
  autoRedirectInterval: any;
  name = '';
  agreeControct = false;
  agreeContract = false;
  isReadContract = false;
  detectContructReadStatus(event: any): void {
    this.isReadContract = event.target.scrollTop === (event.target.scrollHeight - event.target.clientHeight);
  phoneSuccessConfirmVisable = false;
  emailOtpConfirmVisable = false;
  registerDialogVisible = false;
  registerSuccessConfirmVisable = false;
  applyAccount_onAction = false;
  previousPath = '';
  /////////////////////////////////////////////////////
  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() {
    this.removeOtpTime();
    clearInterval(this.otpInterval);
    clearInterval(this.emailResendInterval);
    clearInterval(this.autoRedirectInterval);
  }
  //////////////////////////////////////////////////////////
  //////////////////// 登入
  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 ;
    }
    this.applyAccount_onAction = true;
    const registerInfo = this.setRegisterInfo();
    loginService.register(registerInfo).then(res => {
      this.storageIdToken(res.id_token);
      this.storageRole(Role.USER);
      this.storagePhoneOrEmail(registerInfo);
      this.autoRedirect();
      this.registerSuccessConfirmVisable = true;
    }).catch(() => {
      this.applyAccount_onAction = false;
    });
  };
  private autoRedirect() {
    this.autoRedirectInterval = setInterval(() => {
      this.autoRedirectCounter -= 1;
      if (this.autoRedirectCounter === 0) {
        clearInterval(this.autoRedirectInterval);
        this.redirect();
      }
    }, 1000)
  }
  private redirect() {
    const backToPrevious = ['questionnaire', 'myConsultantList'];
    const find = backToPrevious.findIndex(item => this.previousPath.includes(item));
    console.log(this.previousPath, find, 'redirect');
    find > -1 ? this.$router.go(-1) : this.$router.push('/');
  }
  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;
    }
  };
  //////////////////// 發送/重發/刪除驗證碼
  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);
      }
    });
  };
  private storageOtpTime(type: string, otpInfo: OtpInfo) {
    type === 'MOBILE' ? this.phoneOtpIndexKey = otpInfo.indexKey : this.emailOtpIndexKey = otpInfo.indexKey;
    const info = {...this.setRegisterInfo(), time: new Date()}
    const storageName = type === 'MOBILE' ? OtpStorageName.PHONE : OtpStorageName.EMAIL;
    otpService.setOtpTimeToStorage(storageName, info);
  }
  private startOtpSetting(type: string) {
    if (type === 'MOBILE') {
      this.onPhoneVerifyStep = 'INPUT_OTP';
    } else {
      this.onEmailVerifyResendStatus = 'CAN_RESEND';
      this.emailOtpConfirmVisable = true;
    }
  }
  private startOtpCount(type: string) {
    type === 'MOBILE' ? this.startPhoneCounter() : this.startEmailCounter();;
  }
  private startEmailCounter() {
    this.emailResendInterval = setInterval(() => {
      this.emailCounterSec -= 1;
      if (this.emailResendCounter !== 0) {
        this.emailResendCounter -= 1;
      }
      if (this.emailCounterSec === 0) {
        clearInterval(this.emailResendInterval);
      }
    }, 1000)
  }
  private startPhoneCounter() {
    this.otpInterval = setInterval(() => {
      this.otpCounterSec -= 1;
      if (this.otpResendCounter !== 0) {
        this.otpResendCounter -= 1;
      }
      if (this.otpCounterSec === 0) {
        clearInterval(this.otpInterval)
      }
    }, 1000)
  }
  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{
    const info = {...registerInfo, time: new Date()}
    localStorage.setItem('userInfo',JSON.stringify(info));
  }
  private removeOtpTime() {
    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.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';
    return this.connectDevice === 'EMAIL' && this.onEmailVerifyResendStatus === 'CAN_RESEND';
  };
  applyOtpVerification(): void {
    this.onPhoneVerifyStep = 'INPUT_OTP';
  };
  get phoneValid() {
    const rule = /^09[0-9]{8}$/;
    return this.phoneNumber ? rule.test(this.phoneNumber) : true;
  }
  applyAccount(): void {
    console.log('apply new account!')
  };
  // TODO: 僅OTP認證開發前 暫時使用
   fakeLogin() {
        const user = {
            username: 'user',
            password: 'user',
        }
        login(user).then((res) => {
            localStorage.setItem('id_token', res.data.id_token);
            localStorage.setItem('roleOfState',Role.USER);
            this.$router.go(-1);
        })
  };
  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>
<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;
      @include desktop {
        margin-bottom: 30px;
      }
    }
  }
}
.pam-input {
  height: 26px;
  width: calc(100% - 36px);
  border-radius: 10px !important;
  padding: 12px 18px !important;
  border-width: 1px;
  outline: none;
  @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-otp-resend-btn {
  background: transparent;
  border: none;
  color: $PRIMARY_RED;
  font-weight: bold;
  i {
    margin-right: 10px;
  }
  &.disabled {
    color: $LIGHT_GREY;
  }
}
.pam-register-dialog__contract {
  $DEVICE_EXTRA_HEIGHT: 42px;
  $DEVICE_EXTRA_HEIGHT: 80px;
  $ALIGN_PADDING: 60px;
  $TOP_CONTENT_HEIGHT: 186px;
  $BOTTOM_CONTENT_HEIGHT: 131px;
  $TOP_CONTENT_HEIGHT: 211px;
  $BOTTOM_CONTENT_HEIGHT: 141px;
  // text-align:start;
  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;
}
.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;
  }
  .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;
  }
  .el-dialog__footer {
    padding: 0 !important;
  }
}
  .pam-field-title__hint {
    @extend .smTxt_bold;
    color: #68737A;
  }
  .error {
    @extend .smTxt_bold;
    @extend .text--primary;
    height: 16px;
  }
  .pam-popUp-title {
      font-size: 20px;
      line-height: 27px;
  }
  .pam-popUp-txt {
    font-size: 18px;
    color: $MID_GREY;
  }
  .disabled {
    color: #A7A8AA;
  }
  .pam-input-position {
    position: relative;
    .icon-close {
      cursor: pointer;
      position: absolute;
      right: 15px;
      top: 28px;
      font-size: 16px;
    }
  }
</style>