|
|
<template> <div :class="['tw-h-full tw-p-[30px] tw-bg-white md:tw-bg-primary-pale']"> <div class="xl:tw-grid xl:tw-grid-cols-[auto_414px] xl:tw-gap-[96px] xl:tw-max-w-[1246px] xl:tw-mx-auto xl:tw-px-[60px]"> <div class="tw-hidden xl:tw-block xl:tw-mt-[30px]"> <p class="welcome tw-text-primary-light">{{ $t("Welcome to ShowEasy") }}</p> <p class="sub tw-text-neutral-400"> {{ $t( "Your best guide from trip to show and from show to the world." ) }} </p> <img class="mt-11 ml-15" :src="require('@/assets/img/UserLoginMain.png')" /> </div> <div class="md:tw-w-[414px] md:tw-mx-auto"> <div class="tw-bg-white tw-mt-[30px] md:tw-rounded-[24px] md:tw-pt-[60px] md:tw-pb-[150px] md:tw-px-[30px]"> <h1 class="tw-text-[40px] tw-font-bold tw-mb-[20px] md:tw-text-[24px]">{{ $t('Login') }}</h1> <p class="tw-body-3 tw-text-neutral-400 tw-mb-[16px] md:tw-mb-[12px]"> {{ $t('Welcome back! Please enter your details') }} </p> <p class="tw-body-3 tw-mb-[24px] md:tw-mb-[32px]">{{ $t('Not a member?') }} <nuxt-link :to="localePath('/user/signup')" class="primary--text text-decoration-none">{{ $t('Sign up') }}</nuxt-link> </p> <!-- <div class="tw-grid tw-grid-cols-1 tw-gap-[10px] tw-mb-[30px] md:tw-gap-[12px] md:tw-mb-[12px]"> <button @click="googleLogin" class="tw-block tw-w-full tw-py-[8px] tw-rounded-[16px] tw-border tw-border-solid tw-text-black tw-border-neutrals-200"><img width="20px" height="20px" src="~/assets/img/g-normal.png" class="mr-5" />{{ $t('Login with Google') }}</button> <button @click="facebookLogin" class="tw-block tw-w-full tw-py-[8px] tw-rounded-[16px] tw-border tw-border-solid tw-text-black tw-border-neutrals-200"><img width="20px" height="20px" src="~/assets/img/f_logo_RGB-Blue_72.png" class="mr-5" /> {{ $t("Login with Facebook") }}</button> </div> <div class="tw-grid tw-grid-cols-[auto_16px_auto] tw-gap-[28px] tw-mb-[6px]"> <div class="tw-flex tw-justify-center tw-items-center"> <div class="tw-w-full tw-h-[1px] tw-bg-neutral-200"></div> </div> <div class="tw-text-neutral-400 tw-body-3 tw-font-normal">{{ $t("or") }}</div> <div class="tw-flex tw-justify-center tw-items-center"> <div class="tw-w-full tw-h-[1px] tw-bg-neutral-200"></div> </div> </div> --> <div v-if="serviceExceptionActive" class="warning--text text-size-14 ps-1 mb-3"> {{ $t('Service exception') }} </div> <div v-if="wrongMessageActive" class="warning--text text-size-14 ps-1 mb-3"> {{ $t('The username or password entered is incorrect') }} </div> <v-form ref="loginFormRef" lazy-validation> <!-- <div v-if="$auth.$storage.getUniversal('userAccount') && $auth.$storage.getUniversal('userPassword')"></div> <div v-else></div> --> <v-text-field v-model="userData.Account" background-color="neutrals darken-1" :label="this.$t('Email')" :placeholder="this.$t('Email')" height="40px" filled rounded dense single-line persistent-placeholder :rules="[rules.email,rules.require]" v-on:input="updateValid" /> <v-text-field v-model="userData.Password" background-color="neutrals darken-1" :label="this.$t('Password')" :type=" showPass ? 'text' : 'password'" :placeholder="this.$t('Password')" filled rounded dense single-line persistent-placeholder :append-icon=" showPass ? 'mdi-eye' : 'mdi-eye-off'" @click:append="showPass = !showPass" :rules="[rules.checkPassword,rules.require]" v-on:input="updateValid" @keyup.enter="userLogin" /> </v-form> <div class="tw-flex tw-justify-between tw-items-center tw-mb-[28px] md:tw-mb-[32px]"> <div class="tw-flex tw-items-center"> <div class="tw-flex tw-items-center"> <div class="tw-flex tw-flex-col"> <label class="tw-body-4 container-checkbox" for="remember"> {{ $t('Remember me') }} <input id="remember" type="checkbox" value="remember" v-model="remember" /> <span class="checkmark"></span> </label> </div> </div> </div> <div class="tw-flex tw-items-center"> <nuxt-link class="complementary--text text-decoration-none text-size-14" :to="localePath('/user/forgot')">{{ $t('Forgot Password?') }}</nuxt-link> </div> </div> <div class="md:tw-flex md:tw-justify-center md:tw-items-center"> <button @click="userLogin" :disabled="!valid" :class="['tw-block tw-w-full tw-py-[10px] tw-rounded-[16px] tw-border tw-border-solid tw-body-3 tw-font-normal tw-transition-all tw-duration-200 tw-ease-in-out',valid?'tw-text-white tw-bg-primary-default tw-border-primary-default':'tw-text-base-disable tw-bg-neutral-100 tw-border-neutral-100']">{{ $t("Login") }}</button></div> <!-- 認證會員Modal(連結) --> <v-dialog v-model="dialog" :width="$vuetify.breakpoint.smAndUp ? 423 : 294" @click:outside="colseDialog()"> <v-card class="tw-p-[30px]" :height="$vuetify.breakpoint.smAndUp ? 289 : 290"> <v-spacer class="d-flex align-center tw-justify-between tw-mb-[30px]"> <div class="tw-text-[20px] tw-font-bold tw-text-black"> {{ $t("Verify your email") }} </div> <v-btn @click="colseDialog()" icon> <v-icon> mdi-close </v-icon> </v-btn> </v-spacer> <v-spacer class="tw-mb-[40px]"> <div class="tw-text-[16px] tw-text-neutrals-800"> {{ $t("Oops! Seems like you haven't verified your email,please click the button below to resend a verification email.")}} </div> </v-spacer> <button @click="resendVerifyEmail()" :class="['tw-text-white tw-bg-primary-1 hover:tw-bg-primary-light tw-text-[18px] tw-rounded-[16px] tw-px-[77px] tw-py-[13px]']"> {{ $t("Resend verification email") }} </button> </v-card> </v-dialog> <!-- 重啟帳號Modal --> <v-dialog v-model="deleteDialog" :width="$vuetify.breakpoint.smAndUp ? 423 : 294" @click:outside="colseDialog()"> <v-card class="tw-p-[30px]" :height="$vuetify.breakpoint.smAndUp ? 289 : 290"> <v-spacer class="d-flex tw-justify-between align-center tw-mb-[30px]"> <div class="tw-text-[20px] tw-text-black tw-font-bold"> {{ $t("Reactivate your account") }} </div> <v-btn @click="colseDialog()" icon> <v-icon> mdi-close </v-icon> </v-btn> </v-spacer> <v-spacer class="tw-mb-[40px]"> <div class="tw-text-[16px] tw-text-neutrals-800 tw-font-bold"> {{ $t("Welcome back!")}} </div> <div class="tw-text-[16px] tw-text-neutrals-800"> {{ $t("Looks like your account has been deactivated.")}} <br /> {{ $t("Would you like to reactivate this account?")}} </div> </v-spacer> <button @click="ReactivateAccount()" class="tw-bg-primary-1 tw-text-white hover:tw-bg-primary-light tw-text-[18px] tw-rounded-[16px] tw-px-[86px] tw-py-[13px]"> {{ $t("Reactivate my account") }} </button> <!-- <v-btn class="primary tw-w-auto" rounded :disabled="countdown > 0"> <span v-if="countdown > 0"> {{ `(${this.countdown})` }} </span> </v-btn> --> </v-card> </v-dialog> <VerifyCode @user-verifyCode="userVerifyCode" @resend-mail="resendVerifyEmail" :error="error" :account="userData.Account"></VerifyCode> </div> </div> </div> </div> </template> <script> import { getFirstName } from "~/utils/common"; import VerifyCode from "@/components/newcomponent/modal/VerifyCodeModal.vue"; export default { name: "login", layout: "login", auth: false, components: { VerifyCode }, data() { return { timer: null, showPass: false, resendDialog: false, wrongMessageActive: false, verifyEmailSent: false, serviceExceptionActive: false, valid: false, remember: false, countdown: 60, userData: { Account: '', Password: '', }, rules: { require: value => !!value || this.$t('Required.'), email: v => /^([a-zA-Z0-9_\-\.]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5})$/.test(v) || this.$t('Invalid email'), // checkPassword: v => (/(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])/.test(v) && v.length >= 8 && v.length <= 20) || '請輸入密碼',
checkPassword: v => v.length >= 1 || '請輸入密碼', }, deleteDialog: false, dialog: false, expireTime: new Date(), error: false, userInfo: {}, } }, watch: { remember: { handler: function () { if (this.remember == true) { this.$auth.$storage.setUniversal("userPassword", this.userData.Password); this.$auth.$storage.setUniversal("userAccount", this.userData.Account); }else{ this.$auth.$storage.removeUniversal("userPassword"); this.$auth.$storage.removeUniversal("userAccount", this.userData.Account); } }, }, }, created(){ if(this.$auth.$storage.getUniversal('userAccount') && this.$auth.$storage.getUniversal('userPassword')){ this.checkExpireTime(); } }, mounted(){ if(this.$auth.$storage.getUniversal('userAccount') && this.$auth.$storage.getUniversal('userPassword')){ this.remember = true; }else{ this.remember = false; }
var userAccount = this.$auth.$storage.getUniversal('userAccount'); var userPassword = this.$auth.$storage.getUniversal('userPassword');
this.userData.Account = userAccount ? userAccount : ''; this.userData.Password = userPassword ? userPassword : '';
if(this.userData.Account !=='' && this.userData.Password !==''){ this.valid = true; }else{ this.valid = false; }
}, methods: { colseDialog(){ this.dialog = false; this.deleteDialog = false; }, //登入
async userLogin() { let that = this; if (!that.$refs.loginFormRef.validate()) return; try { const response =await that.$auth.loginWith('local', { data: that.userData }); that.serviceExceptionActive = false; if(response.data.STATUSCODE==200){ let data = response.data.DATA; if(data.authtoken){ const authtoken = data.authtoken; that.$auth.$storage.removeUniversal('authtoken'); that.$auth.$storage.setUniversal('authtoken', authtoken); let path = that.$auth.$storage.getUniversal('userBeforePath'); if(path == "/user"){ path = "/"; } that.$router.push({path: path}); } }else if(response.data.STATUSCODE==500){ that.$auth.redirect('login'); }else if(response.data.STATUSCODE==401){ if(response.data.MSG == "0"){ this.resendVerifyEmail(); this.$modal.show('VerifyCode'); }else if(response.data.MSG == "2"){ that.deleteDialog = true; }else if(response.data.MSG == "帳號或密碼不正確"){ that.wrongMessageActive = true; } }else{ // that.resendDialog = !that.resendDialog;
that.wrongMessageActive = true; } } catch(err) { console.log(err); that.serviceExceptionActive = true; // if(err && err.response && err.response.status){
// err.response.status === 403 ? that.resendDialog = !that.resendDialog : err.response.status === 401 ? that.wrongMessageActive = true : that.resendDialog;
// }
} }, //重新寄出認證信
resendVerifyEmail() { this.$axios .post( `/trending/api/Signup/ReSendVerifyMail?Email=${this.userData.Account}` ) .then((response) => { if(response && response.data && response.data.DATA && response.data.DATA.rel){ let data = response.data.DATA.rel if(data){ this.userInfo = data this.$modal.show('VerifyCode'); } } }) .catch((error) => { console.log(error); }); }, //認證會員
userVerifyCode(value){ this.error = false; this.$axios .get( `/trending/api/Signup/VerifyAccount?OrgID=${this.userInfo.OrgID}&MemberID=${this.userInfo.MemberID}&Code=${value}` ) .then((response) => { //console.log(response);
if(response.data.STATUSCODE == 200){ this.$modal.hide('VerifyCode'); this.Login(); } else{ this.error = true; } }) .catch((err) => { console.log(err); }); }, //重啟帳號
ReactivateAccount(){ this.$axios .post( `/trending/api/Members/ReactivateAccountByAcc?Account=${this.userData.Account}` ) .then((response) => { //console.log(JSON.stringify(response))
if(response && response.data && response.data.DATA && response.data.DATA.rel){ let data = response.data.DATA.rel if(data){ this.deleteDialog = false;
} } }) .catch((error) => { console.log(error); }); }, updateValid(){ if(this.userData.Account !=='' && this.userData.Password !==''){ this.valid = true; }else{ this.valid = false; } }, checkExpireTime(){ this.$axios .get(`/trending/api/System/RememberMe?Account=${this.$auth.$storage.getUniversal('userAccount')}`) .then((response) => { //console.log(response);
const data = response.data.DATA.authtoken; this.expireTime = new Date(data.ExpireTime); const now = new Date(Date.now());
const saveTime = this.expireTime - now; if(saveTime >= 0){ const hour = saveTime / (60 * 60 * 1000);
if(hour == 0){ this.$auth.$storage.removeUniversal('userPassword'); this.$auth.$storage.removeUniversal('userAccount'); } }else{ this.$auth.$storage.removeUniversal('userPassword'); this.$auth.$storage.removeUniversal('userAccount'); } }) .catch((error) => { console.log(error); });
} }, beforeUnmount() { if(this.timer!=null){ clearInterval(this.timer); } }, beforeRouteEnter(to, from, next) { next(vm => { if (from.name) { if (!from.path.includes('user')) { vm.$auth.$storage.setUniversal("userBeforePath", from.fullPath, true) } } if (vm.$auth.loggedIn) { vm.$router.push({path: vm.$auth.$storage.getUniversal('userBeforePath') || '/'}) } else { next() } }) }, } </script> <style lang="scss" scoped> $border-style: 1px solid #E5E5E5; #app { overflow-y: hidden; }
.welcome { color: #f5cda8; font-family: Damion; font-size: 48px; margin-bottom: 0px; font-weight: 400; line-height: 66px; letter-spacing: 0.02em; }
.sub { color: #9c9c9c; font-style: italic; font-weight: 400; font-size: 22px; line-height: 29px; letter-spacing: 0.02em; }
.title { font-weight: 700; font-size: 26px; line-height: 34px; letter-spacing: 0.02em; color: #232323; } .btn-border { border: $border-style; } .seperator { border-bottom: $border-style; text-align: center; height: 12px; margin: 20px 0 30px; } :deep(.v-text-field.v-text-field--enclosed .v-text-field__details) { margin-bottom: 0; padding: 0; .v-messages { display: none; } .v-messages.error--text { display: block; margin-top: 4px; margin-bottom: 16px; } } /* The container */ .container-checkbox { display: block; position: relative; padding-left: 28px; cursor: pointer; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } /* Hide the browser's default checkbox */ .container-checkbox input { position: absolute; opacity: 0; cursor: pointer; } /* Create a custom checkbox */ .container-checkbox .checkmark { position: absolute; top: 0; left: 0; height: 18px; width: 18px; background-color: transparent; border: 1px solid #f48800; border-radius: 4px; } /* On mouse-over, add a grey background color */ .container-checkbox:hover input~.checkmark { border-color: #f48800; } /* When the checkbox is checked, add a blue background */ .container-checkbox input:checked~.checkmark { background-color: #f48800; border-color: #f48800; } /* Create the checkmark/indicator (hidden when not checked) */ .container-checkbox .checkmark:after { content: ""; position: absolute; display: none; } /* Show the checkmark when checked */ .container-checkbox input:checked~.checkmark:after { display: block; } /* Style the checkmark/indicator */ .container-checkbox .checkmark:after { left: 5px; top: 2px; width: 5px; height: 10px; border: solid #ffffff; border-width: 0 2px 2px 0; -webkit-transform: rotate(45deg); -ms-transform: rotate(45deg); transform: rotate(45deg); } </style>
|