Merge branch 'main' of ssh://18.167.251.121:10002/aidlab/Aida_Purchaser_Front
This commit is contained in:
3
src/assets/icons/dui.svg
Normal file
3
src/assets/icons/dui.svg
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<svg width="20" height="14" viewBox="0 0 20 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M19.7269 0.156104C19.5188 -0.0520347 19.1025 -0.0520347 18.8944 0.156104L7.13454 11.9159C6.97843 12.0721 6.66622 12.0721 6.51012 11.9159L0.994441 6.40027C0.786302 6.19213 0.370025 6.19213 0.161886 6.40027C-0.0462532 6.60841 0.00578167 6.66044 0.00578167 6.81655C0.00578167 6.97265 0.0578162 7.12876 0.161886 7.23283L6.40605 13.477C6.51012 13.5811 6.66622 13.6331 6.82233 13.6331C6.97843 13.6331 7.13454 13.5811 7.23861 13.477L19.7269 0.98866C19.831 0.88459 19.883 0.728486 19.883 0.572382C19.883 0.416278 19.831 0.260174 19.7269 0.156104Z" fill="#232323"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 669 B |
@@ -7,9 +7,11 @@ export default {
|
|||||||
name: 'Name',
|
name: 'Name',
|
||||||
email: 'Email',
|
email: 'Email',
|
||||||
password: 'Password',
|
password: 'Password',
|
||||||
|
passwordConfirmation: 'Password Confirmation',
|
||||||
enterName: 'Enter your name',
|
enterName: 'Enter your name',
|
||||||
enterEmail: 'Enter your email',
|
enterEmail: 'Enter your email',
|
||||||
enterPassword: 'Enter your password',
|
enterPassword: 'Enter your password',
|
||||||
|
enterPasswordAgain: 'Enter your password again',
|
||||||
forgotPassword: 'Forget password?',
|
forgotPassword: 'Forget password?',
|
||||||
pleaseInputName: 'Please input the name',
|
pleaseInputName: 'Please input the name',
|
||||||
nameLengthError: 'Name length must be between {min} and {max} characters',
|
nameLengthError: 'Name length must be between {min} and {max} characters',
|
||||||
@@ -28,7 +30,7 @@ export default {
|
|||||||
havenAccountToLogin: `Already have an account? <span onclick="onClickLogin()">Log in</span>`,
|
havenAccountToLogin: `Already have an account? <span onclick="onClickLogin()">Log in</span>`,
|
||||||
verifyEmail: 'Verify your email address',
|
verifyEmail: 'Verify your email address',
|
||||||
verifyCodeHasSent: 'A verification code has been sent to<br><span>{email}</span>',
|
verifyCodeHasSent: 'A verification code has been sent to<br><span>{email}</span>',
|
||||||
verify: 'Verify',
|
verify: 'VERIFY',
|
||||||
resendCode: 'Resend Code',
|
resendCode: 'Resend Code',
|
||||||
resendCodeIn: 'Resend Code in {time}',
|
resendCodeIn: 'Resend Code in {time}',
|
||||||
orContinueWith: 'or continue with',
|
orContinueWith: 'or continue with',
|
||||||
|
|||||||
@@ -8,9 +8,11 @@ export default {
|
|||||||
name: '姓名',
|
name: '姓名',
|
||||||
email: '邮箱',
|
email: '邮箱',
|
||||||
password: '密码',
|
password: '密码',
|
||||||
|
passwordConfirmation: '密码确认',
|
||||||
enterName: '请输入姓名',
|
enterName: '请输入姓名',
|
||||||
enterEmail: '请输入邮箱',
|
enterEmail: '请输入邮箱',
|
||||||
enterPassword: '请输入密码',
|
enterPassword: '请输入密码',
|
||||||
|
enterPasswordAgain: '请输入密码确认',
|
||||||
forgotPassword: '忘记密码?',
|
forgotPassword: '忘记密码?',
|
||||||
pleaseInputName: '请输入姓名',
|
pleaseInputName: '请输入姓名',
|
||||||
nameLengthError: '姓名长度必须在 {min} 到 {max} 个字符之间',
|
nameLengthError: '姓名长度必须在 {min} 到 {max} 个字符之间',
|
||||||
|
|||||||
@@ -38,7 +38,7 @@
|
|||||||
--el-input-border-radius: 0;
|
--el-input-border-radius: 0;
|
||||||
--el-input-text-color: #232323;
|
--el-input-text-color: #232323;
|
||||||
--el-border-color: #C4C4C4;
|
--el-border-color: #C4C4C4;
|
||||||
font-size: 1.4rem;
|
font-size: 1rem;
|
||||||
}
|
}
|
||||||
.retrieve-password:deep(.el-form) .el-input::placeholder,
|
.retrieve-password:deep(.el-form) .el-input::placeholder,
|
||||||
.register:deep(.el-form) .el-input::placeholder,
|
.register:deep(.el-form) .el-input::placeholder,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="visible-code">
|
<div class="email-verify">
|
||||||
<div class="tip" v-html="$t('Login.verifyCodeHasSent', { email: props.email })"></div>
|
<div class="tip" v-html="$t('Login.verifyCodeHasSent', { email: props.email })"></div>
|
||||||
<input-code @submit="onVerify" v-model="code" ref="inputCodeRef" />
|
<input-code @submit="onVerify" v-model="code" ref="inputCodeRef" />
|
||||||
<p class="time" v-if="time > 0">{{ $t('Login.resendCodeIn', { time: timeStr }) }}</p>
|
<p class="time" v-if="time > 0">{{ $t('Login.resendCodeIn', { time: timeStr }) }}</p>
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
<span @click="onResend">{{ $t('Login.resendCode') }}</span>
|
<span @click="onResend">{{ $t('Login.resendCode') }}</span>
|
||||||
</p>
|
</p>
|
||||||
<button class="verify" custom="black" @click="onVerify">{{ $t('Login.verify') }}</button>
|
<button class="verify" custom="black" @click="onVerify">{{ $t('Login.verify') }}</button>
|
||||||
<other-login />
|
<other-login v-if="isShowOtherLogin" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -29,7 +29,8 @@
|
|||||||
type: String as () => 'LOGIN' | 'REGISTER' | 'FORGOT_PWD',
|
type: String as () => 'LOGIN' | 'REGISTER' | 'FORGOT_PWD',
|
||||||
required: true
|
required: true
|
||||||
},
|
},
|
||||||
password: { type: String, default: '' }
|
password: { type: String, default: '' },
|
||||||
|
isShowOtherLogin: { type: Boolean, default: true }
|
||||||
})
|
})
|
||||||
const code = ref('')
|
const code = ref('')
|
||||||
const time = ref(60)
|
const time = ref(60)
|
||||||
@@ -96,7 +97,7 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
.visible-code {
|
.email-verify {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@@ -123,17 +124,15 @@
|
|||||||
--button-font-size: 1.4rem;
|
--button-font-size: 1.4rem;
|
||||||
}
|
}
|
||||||
> .time {
|
> .time {
|
||||||
|
font-family: KaiseiOpti-Regular;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
margin-top: 2.4rem;
|
margin-top: 2.4rem;
|
||||||
font-size: 1.6rem;
|
font-size: 1.2rem;
|
||||||
color: #666;
|
color: #666;
|
||||||
font-family: Regular;
|
|
||||||
> span {
|
> span {
|
||||||
color: #ff7a50;
|
color: #232323;
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
font-weight: 500;
|
|
||||||
font-family: Medium;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
> .other-login {
|
> .other-login {
|
||||||
|
|||||||
@@ -1,117 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="index">
|
|
||||||
<div class="header">
|
|
||||||
<span class="tip">{{ $t('AlphaVersion') }}</span>
|
|
||||||
<img src="@/assets/images/logo-1.png" class="logo" />
|
|
||||||
<p class="split"></p>
|
|
||||||
<button class="login" @click="onLogin">{{ $t('Login.login') }}</button>
|
|
||||||
<button class="register" @click="onRegister">{{ $t('Login.register') }}</button>
|
|
||||||
</div>
|
|
||||||
<img src="@/assets/images/login/index-title.png" class="title" draggable="false" />
|
|
||||||
<img src="@/assets/images/login/index-zhuangshi.png" class="zhuangshi" draggable="false" />
|
|
||||||
<div class="tip">{{ $t('Login.indexTip') }}</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { computed } from 'vue'
|
|
||||||
import { useRouter } from 'vue-router'
|
|
||||||
const router = useRouter()
|
|
||||||
const onLogin = () => {
|
|
||||||
router.push({ name: 'login' })
|
|
||||||
}
|
|
||||||
const onRegister = () => {
|
|
||||||
router.push({ name: 'register' })
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="less" scoped>
|
|
||||||
.index {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
overflow: hidden;
|
|
||||||
position: relative;
|
|
||||||
background-image: url('@/assets/images/login/index-bg.png');
|
|
||||||
background-size: cover;
|
|
||||||
background-position: center;
|
|
||||||
> .header {
|
|
||||||
position: absolute;
|
|
||||||
top: 3rem;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
> * {
|
|
||||||
position: relative;
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
> .tip {
|
|
||||||
position: absolute;
|
|
||||||
width: 100%;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
font-size: 3rem;
|
|
||||||
text-align: center;
|
|
||||||
font-family: Regular;
|
|
||||||
color: #fff;
|
|
||||||
z-index: 0;
|
|
||||||
}
|
|
||||||
> .logo {
|
|
||||||
width: auto;
|
|
||||||
height: 2.5rem;
|
|
||||||
margin-left: 3.8rem;
|
|
||||||
}
|
|
||||||
> .split {
|
|
||||||
margin: 0 auto;
|
|
||||||
}
|
|
||||||
> button {
|
|
||||||
margin-right: 3rem;
|
|
||||||
width: 20rem;
|
|
||||||
height: 5.2rem;
|
|
||||||
border-radius: 5rem;
|
|
||||||
border: none;
|
|
||||||
outline: none;
|
|
||||||
font-size: 2.2rem;
|
|
||||||
font-weight: 600;
|
|
||||||
font-family: SemiBold;
|
|
||||||
border: 0.2rem solid #fff;
|
|
||||||
&:active {
|
|
||||||
opacity: 0.8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
> .login {
|
|
||||||
background-color: #fff;
|
|
||||||
color: #713e1f;
|
|
||||||
}
|
|
||||||
> .register {
|
|
||||||
background-color: transparent;
|
|
||||||
color: #ffffff;
|
|
||||||
backdrop-filter: blur(10px);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
> .zhuangshi,
|
|
||||||
> .title,
|
|
||||||
> .tip {
|
|
||||||
position: absolute;
|
|
||||||
left: 50%;
|
|
||||||
transform: translateX(-50%);
|
|
||||||
}
|
|
||||||
> .title {
|
|
||||||
// width: 55%;
|
|
||||||
width: 105.6rem;
|
|
||||||
height: auto;
|
|
||||||
top: 20.5rem;
|
|
||||||
}
|
|
||||||
> .zhuangshi {
|
|
||||||
width: 21.5rem;
|
|
||||||
height: auto;
|
|
||||||
bottom: 13.4rem;
|
|
||||||
}
|
|
||||||
> .tip {
|
|
||||||
font-size: 2.8rem;
|
|
||||||
font-family: Regular;
|
|
||||||
color: #fff;
|
|
||||||
bottom: 8rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -32,7 +32,7 @@
|
|||||||
--el-input-border-radius: 0;
|
--el-input-border-radius: 0;
|
||||||
--el-input-text-color: #232323;
|
--el-input-text-color: #232323;
|
||||||
--el-border-color: #C4C4C4;
|
--el-border-color: #C4C4C4;
|
||||||
font-size: 1.4rem;
|
font-size: 1rem;
|
||||||
|
|
||||||
&::placeholder {
|
&::placeholder {
|
||||||
color: #9F9F9F;
|
color: #9F9F9F;
|
||||||
|
|||||||
@@ -10,7 +10,6 @@
|
|||||||
:close-on-click-modal="false"
|
:close-on-click-modal="false"
|
||||||
>
|
>
|
||||||
<div class="login-dialog-content">
|
<div class="login-dialog-content">
|
||||||
<img class="bg" src="@/assets/images/login/bg.jpg" />
|
|
||||||
<img class="logo" src="@/assets/images/logo.png" />
|
<img class="logo" src="@/assets/images/logo.png" />
|
||||||
<div class="close" @click="show = false"><svg-icon name="close" /></div>
|
<div class="close" @click="show = false"><svg-icon name="close" /></div>
|
||||||
<div class="content" v-if="curentTabInfo">
|
<div class="content" v-if="curentTabInfo">
|
||||||
@@ -22,8 +21,10 @@
|
|||||||
<div class="nav" v-show="!curentTabInfo.title">
|
<div class="nav" v-show="!curentTabInfo.title">
|
||||||
<div
|
<div
|
||||||
class="item"
|
class="item"
|
||||||
:class="{ active: currentTab === TabNames.sign_up }"
|
:class="{
|
||||||
@click="currentTab = TabNames.sign_up"
|
active: [TabNames.register, TabNames.register_success].includes(currentTab)
|
||||||
|
}"
|
||||||
|
@click="currentTab = TabNames.register"
|
||||||
>
|
>
|
||||||
SIGN UP
|
SIGN UP
|
||||||
</div>
|
</div>
|
||||||
@@ -42,6 +43,7 @@
|
|||||||
@login="onLogin"
|
@login="onLogin"
|
||||||
@register="onRegister"
|
@register="onRegister"
|
||||||
@submit-email-code="onSubmitEmailCode"
|
@submit-email-code="onSubmitEmailCode"
|
||||||
|
@back="onBack"
|
||||||
:name="data.name"
|
:name="data.name"
|
||||||
:email="data.email"
|
:email="data.email"
|
||||||
:password="data.password"
|
:password="data.password"
|
||||||
@@ -58,6 +60,8 @@
|
|||||||
import login from './login.vue'
|
import login from './login.vue'
|
||||||
import register from './register.vue'
|
import register from './register.vue'
|
||||||
import emailVerify from './email-verify.vue'
|
import emailVerify from './email-verify.vue'
|
||||||
|
import registerSuccess from './register-success.vue'
|
||||||
|
import retrievePassword from './retrieve-password.vue'
|
||||||
import myEvent from '@/utils/myEvent'
|
import myEvent from '@/utils/myEvent'
|
||||||
const data = ref({
|
const data = ref({
|
||||||
name: '',
|
name: '',
|
||||||
@@ -65,11 +69,11 @@
|
|||||||
password: '',
|
password: '',
|
||||||
type: ''
|
type: ''
|
||||||
})
|
})
|
||||||
const show = ref(false)
|
|
||||||
const TabNames = {
|
const TabNames = {
|
||||||
login: 'login',
|
login: 'login',
|
||||||
sign_up: 'sign_up',
|
register: 'register',
|
||||||
email_verify: 'email_verify',
|
email_verify: 'email_verify',
|
||||||
|
register_success: 'register_success',
|
||||||
retrieve_password: 'retrieve_password'
|
retrieve_password: 'retrieve_password'
|
||||||
}
|
}
|
||||||
const tabList = markRaw([
|
const tabList = markRaw([
|
||||||
@@ -78,7 +82,7 @@
|
|||||||
component: login
|
component: login
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: TabNames.sign_up,
|
name: TabNames.register,
|
||||||
component: register
|
component: register
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -89,15 +93,20 @@
|
|||||||
{
|
{
|
||||||
name: TabNames.retrieve_password,
|
name: TabNames.retrieve_password,
|
||||||
title: 'RETRIEVE PASSWORD',
|
title: 'RETRIEVE PASSWORD',
|
||||||
component: login
|
component: retrievePassword
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: TabNames.register_success,
|
||||||
|
component: registerSuccess
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
|
const show = ref(false)
|
||||||
const currentTab = ref(TabNames.login)
|
const currentTab = ref(TabNames.login)
|
||||||
const curentTabInfo = computed(() => tabList.find((v) => v.name === currentTab.value))
|
const curentTabInfo = computed(() => tabList.find((v) => v.name === currentTab.value))
|
||||||
const lastTab = ref('')
|
const lastTab = ref('')
|
||||||
watch(currentTab, (v, o) => (lastTab.value = o))
|
watch(currentTab, (v, o) => (lastTab.value = o))
|
||||||
const onBack = () => {
|
const onBack = () => {
|
||||||
if (lastTab.value) currentTab.value = lastTab.value
|
currentTab.value = lastTab.value || TabNames.login
|
||||||
}
|
}
|
||||||
const open = (type?: string) => {
|
const open = (type?: string) => {
|
||||||
currentTab.value = TabNames[type] || TabNames.login
|
currentTab.value = TabNames[type] || TabNames.login
|
||||||
@@ -118,13 +127,17 @@
|
|||||||
}
|
}
|
||||||
const onRegister = (res: any) => {
|
const onRegister = (res: any) => {
|
||||||
data.value = res
|
data.value = res
|
||||||
data.value.type = TabNames.sign_up
|
data.value.type = TabNames.register
|
||||||
currentTab.value = TabNames.email_verify
|
currentTab.value = TabNames.email_verify
|
||||||
}
|
}
|
||||||
const onSubmitEmailCode = (code: string) => {
|
const onSubmitEmailCode = (code: string) => {
|
||||||
// data.value.code = code
|
if (data.value.type === TabNames.login) {
|
||||||
console.log(code)
|
console.log('登录', code)
|
||||||
show.value = false
|
show.value = false
|
||||||
|
} else {
|
||||||
|
console.log('注册', code)
|
||||||
|
currentTab.value = TabNames.register_success
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -147,14 +160,16 @@
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
background: url('@/assets/images/login/bg.jpg') no-repeat center center / 100% 100%;
|
||||||
|
> *:not(.content) {
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
> .bg {
|
> .bg {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
> * {
|
|
||||||
position: absolute;
|
|
||||||
}
|
|
||||||
> .logo {
|
> .logo {
|
||||||
width: auto;
|
width: auto;
|
||||||
height: 4rem;
|
height: 4rem;
|
||||||
@@ -170,9 +185,10 @@
|
|||||||
}
|
}
|
||||||
> .content {
|
> .content {
|
||||||
width: 34rem;
|
width: 34rem;
|
||||||
top: 5rem;
|
|
||||||
right: 6rem;
|
|
||||||
height: calc(100% - 10rem);
|
height: calc(100% - 10rem);
|
||||||
|
margin: 5rem 6rem auto auto;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
> .header {
|
> .header {
|
||||||
--padding-bottom: 1.2rem;
|
--padding-bottom: 1.2rem;
|
||||||
padding-bottom: var(--padding-bottom);
|
padding-bottom: var(--padding-bottom);
|
||||||
|
|||||||
@@ -40,15 +40,15 @@
|
|||||||
.password-tip {
|
.password-tip {
|
||||||
background: #404040;
|
background: #404040;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
font-size: 1.4rem;
|
font-size: 1.1rem;
|
||||||
padding: 2rem;
|
padding: 1.5rem;
|
||||||
border-radius: 2rem;
|
border-radius: 1.5rem;
|
||||||
line-height: normal;
|
line-height: normal;
|
||||||
|
|
||||||
> div {
|
> div {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin-bottom: 0.5rem;
|
margin-bottom: 1rem;
|
||||||
&:last-child {
|
&:last-child {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|||||||
113
src/views/login/register-success.vue
Normal file
113
src/views/login/register-success.vue
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
<template>
|
||||||
|
<div class="register-success">
|
||||||
|
<div class="icon"><svg-icon name="dui" size="20" /></div>
|
||||||
|
<div class="title">Welcome to Stylish Parade!</div>
|
||||||
|
<div class="title">Please switch to the Login tab to log in.</div>
|
||||||
|
<div class="footer">
|
||||||
|
<div class="title">
|
||||||
|
<span class="text">What awaits you in Stylish Parade</span>
|
||||||
|
<span class="icon"><svg-icon name="arrow_right" size="11" /></span>
|
||||||
|
</div>
|
||||||
|
<div class="content">
|
||||||
|
<div>
|
||||||
|
<div class="title">Behind the design</div>
|
||||||
|
<div class="tip">
|
||||||
|
Discover how designers bring ideas to life with AiDA — from first sketch to final look.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="title">Creative digital works</div>
|
||||||
|
<div class="tip">
|
||||||
|
Unlock a growing library of inspiring digital works to refresh your creative mind.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="title">A fashion community</div>
|
||||||
|
<div class="tip">
|
||||||
|
Join a space where fashion speaks — exchange ideas and connect with creators worldwide.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed, onBeforeUnmount, onMounted, ref } from 'vue'
|
||||||
|
import { useI18n } from 'vue-i18n'
|
||||||
|
const { t } = useI18n()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.register-success {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: 7.7rem;
|
||||||
|
> .icon {
|
||||||
|
width: 4rem;
|
||||||
|
height: 4rem;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: #fff;
|
||||||
|
border: 0.1rem solid #e8e8e8;
|
||||||
|
margin-bottom: 1.8rem;
|
||||||
|
}
|
||||||
|
> .title {
|
||||||
|
font-size: 1.6rem;
|
||||||
|
line-height: 2.4rem;
|
||||||
|
text-align: center;
|
||||||
|
color: #232323;
|
||||||
|
}
|
||||||
|
> .footer {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
left: 0;
|
||||||
|
bottom: 7rem;
|
||||||
|
padding: 0 6rem;
|
||||||
|
> .title {
|
||||||
|
font-family: KaiseiOpti-Regular;
|
||||||
|
font-size: 1.4rem;
|
||||||
|
line-height: 2.4rem;
|
||||||
|
color: #666;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-end;
|
||||||
|
margin-bottom: 1.2rem;
|
||||||
|
> .icon {
|
||||||
|
margin-left: 1.2rem;
|
||||||
|
transform: rotate(90deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
> .content {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 1.8rem;
|
||||||
|
> div {
|
||||||
|
padding: 2.4rem 1.5rem 0;
|
||||||
|
height: 14.8rem;
|
||||||
|
background: rgba(255, 255, 255, 0.9);
|
||||||
|
box-shadow: 3px 4px 8px 0px rgba(0, 0, 0, 0.11);
|
||||||
|
flex: 1;
|
||||||
|
&:first-child {
|
||||||
|
flex: 0.84;
|
||||||
|
}
|
||||||
|
> .title {
|
||||||
|
font-family: KaiseiOpti-Bold;
|
||||||
|
font-size: 1.6rem;
|
||||||
|
line-height: 2.4rem;
|
||||||
|
margin-bottom: 1.2rem;
|
||||||
|
color: #232323;
|
||||||
|
}
|
||||||
|
> .tip {
|
||||||
|
font-family: KaiseiOpti-Regular;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
line-height: 1.7rem;
|
||||||
|
color: #585858;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,120 +1,183 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="retrieve-password">
|
<div class="retrieve-password">
|
||||||
<div class="left">
|
<el-form
|
||||||
<img class="bg" src="@/assets/images/login/left-bg.png" />
|
:model="formData"
|
||||||
<img class="logo" src="@/assets/images/logo-1.png" />
|
:rules="ruleForm"
|
||||||
</div>
|
label-position="top"
|
||||||
<div class="right">
|
ref="form1Ref"
|
||||||
<div class="top">
|
v-show="index === 0"
|
||||||
<button class="back" @click="onBack">
|
>
|
||||||
<svg-icon name="arrow-left" size="37" />
|
<div class="title">Please enter your email address below to verify your identity.</div>
|
||||||
|
<el-form-item :label="$t('Login.email')" prop="email">
|
||||||
|
<el-input v-model="formData.email" :placeholder="$t('Login.enterEmail')" name="email" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item class="submit-item">
|
||||||
|
<button class="submit" type="submit" custom="black" @click.prevent="onSubmit1">
|
||||||
|
SUBMIT
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</el-form-item>
|
||||||
<div class="box">
|
</el-form>
|
||||||
<img src="@/assets/images/login/elephant.png" />
|
<div class="verify-box" v-if="index === 1">
|
||||||
<template v-if="!isVisible">
|
<email-verify
|
||||||
<div class="title">{{ $t('Login.retrievePassword') }}</div>
|
type="FORGOT_PWD"
|
||||||
<el-form :model="formData" :rules="ruleForm" label-position="top" ref="formRef">
|
:email="formData.email"
|
||||||
<el-form-item :label="$t('Login.email')" prop="email">
|
@submit-email-code="onVerifyCode"
|
||||||
<el-input
|
:is-show-other-login="false"
|
||||||
v-model="formData.email"
|
/>
|
||||||
:placeholder="$t('Login.enterEmail')"
|
|
||||||
name="email"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item :label="$t('Login.password')" prop="password">
|
|
||||||
<password-tip :value="formData.password" v-show="showPasswordTip" />
|
|
||||||
<el-input
|
|
||||||
v-model="formData.password"
|
|
||||||
:placeholder="$t('Login.enterPassword')"
|
|
||||||
type="password"
|
|
||||||
show-password
|
|
||||||
name="password"
|
|
||||||
@blur="showPasswordTip = false"
|
|
||||||
@focus="showPasswordTip = true"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
<br />
|
|
||||||
<br />
|
|
||||||
<el-form-item>
|
|
||||||
<el-button class="submit" type="primary" @click="onSubmit">{{
|
|
||||||
$t('submit')
|
|
||||||
}}</el-button>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
</template>
|
|
||||||
<!-- <visible-code
|
|
||||||
v-show="isVisible"
|
|
||||||
type="FORGOT_PWD"
|
|
||||||
ref="visibleCodeRef"
|
|
||||||
:email="formData.email"
|
|
||||||
@submit="onVerifyCode"
|
|
||||||
/> -->
|
|
||||||
<other-login />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<el-form
|
||||||
|
:model="formData"
|
||||||
|
:rules="ruleForm"
|
||||||
|
label-position="top"
|
||||||
|
ref="form2Ref"
|
||||||
|
v-show="index === 2"
|
||||||
|
>
|
||||||
|
<div class="title">
|
||||||
|
Enter a new password for <br />
|
||||||
|
<span>{{ formData.email }}</span>
|
||||||
|
</div>
|
||||||
|
<el-form-item :label="$t('Login.password')" prop="password">
|
||||||
|
<password-tip :value="formData.password" v-show="showPasswordTip" />
|
||||||
|
<el-input
|
||||||
|
v-model="formData.password"
|
||||||
|
:placeholder="$t('Login.enterPassword')"
|
||||||
|
type="password"
|
||||||
|
show-password
|
||||||
|
name="password"
|
||||||
|
@blur="showPasswordTip = false"
|
||||||
|
@focus="showPasswordTip = true"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<div class="password-warning">
|
||||||
|
<span class="icon"><svg-icon name="warning" size="12" /></span>
|
||||||
|
<span class="label">You must satisfy ALL password conditions to register.</span>
|
||||||
|
</div>
|
||||||
|
<el-form-item :label="$t('Login.passwordConfirmation')" prop="confirmPassword">
|
||||||
|
<el-input
|
||||||
|
v-model="formData.confirmPassword"
|
||||||
|
:placeholder="$t('Login.enterPasswordAgain')"
|
||||||
|
type="password"
|
||||||
|
show-password
|
||||||
|
name="password"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item class="submit-item">
|
||||||
|
<button class="submit" type="submit" custom="black" @click.prevent="onSubmit2">
|
||||||
|
SUBMIT
|
||||||
|
</button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import md5 from 'md5'
|
import md5 from 'md5'
|
||||||
import { ForgotPassword } from '@/api/user'
|
|
||||||
import { computed, reactive, ref } from 'vue'
|
import { computed, reactive, ref } from 'vue'
|
||||||
import { useRouter } from 'vue-router'
|
|
||||||
import { validateEmail, validatePass } from './tools'
|
import { validateEmail, validatePass } from './tools'
|
||||||
import OtherLogin from './other-login.vue'
|
|
||||||
import emailVerify from './email-verify.vue'
|
|
||||||
import PasswordTip from './password-tip.vue'
|
import PasswordTip from './password-tip.vue'
|
||||||
import { useUserInfoStore } from '@/stores'
|
import EmailVerify from './email-verify.vue'
|
||||||
const userInfoStore = useUserInfoStore()
|
const emit = defineEmits(['back'])
|
||||||
const router = useRouter()
|
const validateConfirmPassword = (rule: any, value: string, callback: any) => {
|
||||||
|
if (value !== formData.password) {
|
||||||
|
callback(new Error('Passwords do not match'))
|
||||||
|
} else {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const index = ref(0)
|
||||||
const ruleForm = reactive({
|
const ruleForm = reactive({
|
||||||
email: [{ validator: validateEmail, trigger: 'change' }],
|
email: [{ validator: validateEmail, trigger: 'change' }],
|
||||||
password: [{ validator: validatePass, trigger: 'change' }]
|
password: [{ validator: validatePass, trigger: 'change' }],
|
||||||
|
confirmPassword: [{ validator: validateConfirmPassword, trigger: 'change' }]
|
||||||
})
|
})
|
||||||
const isVisible = ref(false)
|
|
||||||
const showPasswordTip = ref(false)
|
const showPasswordTip = ref(false)
|
||||||
const formData = reactive({
|
const formData = reactive({
|
||||||
email: '',
|
email: '',
|
||||||
password: ''
|
code: '',
|
||||||
|
password: '',
|
||||||
|
confirmPassword: ''
|
||||||
})
|
})
|
||||||
const formRef = ref(null)
|
const form1Ref = ref(null)
|
||||||
const onBack = () => {
|
|
||||||
if (isVisible.value) {
|
|
||||||
isVisible.value = false
|
|
||||||
} else {
|
|
||||||
router.back()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const visibleCodeRef = ref(null)
|
const visibleCodeRef = ref(null)
|
||||||
const onSubmit = () => {
|
const form2Ref = ref(null)
|
||||||
formRef.value?.validate?.((valid) => {
|
const onSubmit1 = () => {
|
||||||
|
form1Ref.value?.validate?.((valid) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
// console.log('submit!')
|
index.value = 1
|
||||||
visibleCodeRef.value?.onSendCode().then(() => {
|
} else {
|
||||||
isVisible.value = true
|
console.warn('error submit!')
|
||||||
})
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const onSubmit2 = () => {
|
||||||
|
form2Ref.value?.validate?.((valid) => {
|
||||||
|
if (valid) {
|
||||||
|
const data = {
|
||||||
|
email: formData.email,
|
||||||
|
code: formData.code,
|
||||||
|
password: md5(formData.password)
|
||||||
|
}
|
||||||
|
console.log(data)
|
||||||
|
emit('back')
|
||||||
} else {
|
} else {
|
||||||
console.warn('error submit!')
|
console.warn('error submit!')
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
const onVerifyCode = (code: string) => {
|
const onVerifyCode = (code: string) => {
|
||||||
// console.log(code)
|
if (!code) return
|
||||||
ForgotPassword({
|
formData.code = code
|
||||||
email: formData.email,
|
index.value = 2
|
||||||
newPassword: md5(formData.password),
|
|
||||||
verificationCode: code
|
|
||||||
})
|
|
||||||
.then((res) => {
|
|
||||||
if (res) router.push({ name: 'login' })
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
console.warn(error)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
@import './less/style.less';
|
@import './less/style.less';
|
||||||
|
|
||||||
|
.retrieve-password {
|
||||||
|
flex: 1;
|
||||||
|
&:deep(.el-form) {
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
.el-form-item.submit-item {
|
||||||
|
margin-top: auto;
|
||||||
|
}
|
||||||
|
.el-input {
|
||||||
|
--el-input-height: 4.8rem;
|
||||||
|
}
|
||||||
|
.el-form-item:nth-last-child(2) {
|
||||||
|
margin-bottom: 10rem;
|
||||||
|
}
|
||||||
|
> .title {
|
||||||
|
font-family: KaiseiOpti-Regular;
|
||||||
|
font-size: 1.6rem;
|
||||||
|
line-height: 2.4rem;
|
||||||
|
text-align: center;
|
||||||
|
color: #585858;
|
||||||
|
margin-top: auto;
|
||||||
|
margin-bottom: 3rem;
|
||||||
|
> span {
|
||||||
|
font-family: KaiseiOpti-Medium;
|
||||||
|
color: #252727;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
> .verify-box {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
&:deep(.email-verify) {
|
||||||
|
> .tip {
|
||||||
|
margin-top: 8rem;
|
||||||
|
}
|
||||||
|
> .input-code {
|
||||||
|
margin-top: 3rem;
|
||||||
|
}
|
||||||
|
> .verify {
|
||||||
|
margin-top: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user