登录页面
This commit is contained in:
parent
2bcd996d58
commit
acce6953fe
@ -73,6 +73,7 @@ export default {
|
|||||||
'/login/other',
|
'/login/other',
|
||||||
'/login/password',
|
'/login/password',
|
||||||
'/login/verification-code',
|
'/login/verification-code',
|
||||||
|
'/login/retrieve-password',
|
||||||
|
|
||||||
|
|
||||||
'/service-protocol',
|
'/service-protocol',
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="button" :class="class1" @click.capture.stop="check">
|
<div class="button" :class="class1" @click.capture.stop="check">
|
||||||
<img v-if="loading" src="../assets/img/icon/loading-white.png" alt="">
|
<img v-show="loading" src="../assets/img/icon/loading-white.png" alt="">
|
||||||
<slot v-if="showText"></slot>
|
<slot v-if="showText"></slot>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@ -2,12 +2,12 @@
|
|||||||
<div class="ConfirmDialog " @click="$emit('dismiss')">
|
<div class="ConfirmDialog " @click="$emit('dismiss')">
|
||||||
<div class="content" @click.stop="null">
|
<div class="content" @click.stop="null">
|
||||||
<div class="body">
|
<div class="body">
|
||||||
<div class="title">{{ title }}</div>
|
<div class="title" v-if="title">{{ title }}</div>
|
||||||
<div class="subtitle" v-if="subtitle">{{ subtitle }}</div>
|
<div class="subtitle" :class="subtitleColor" v-if="subtitle">{{ subtitle }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="footer">
|
<div class="footer">
|
||||||
<div class="cancel" @click.stop="$emit('cancel')">取消</div>
|
<div class="cancel" :class="cancelTextColor" @click.stop="$emit('cancel')">{{ cancelText }}</div>
|
||||||
<div class="ok" @click.stop="$emit('ok')">确定</div>
|
<div class="ok" @click.stop="$emit('ok')">{{ okText }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -31,7 +31,31 @@ export default {
|
|||||||
default() {
|
default() {
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
subtitleColor: {
|
||||||
|
type: String,
|
||||||
|
default() {
|
||||||
|
return 'gray'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
okText: {
|
||||||
|
type: String,
|
||||||
|
default() {
|
||||||
|
return '确定'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
cancelText: {
|
||||||
|
type: String,
|
||||||
|
default() {
|
||||||
|
return '取消'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
cancelTextColor: {
|
||||||
|
type: String,
|
||||||
|
default() {
|
||||||
|
return 'gray'
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {}
|
return {}
|
||||||
@ -58,30 +82,32 @@ export default {
|
|||||||
|
|
||||||
.content {
|
.content {
|
||||||
background: white;
|
background: white;
|
||||||
width: 80%;
|
width: 70%;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
font-size: 1.5rem;
|
font-size: 1.5rem;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
||||||
.body {
|
.body {
|
||||||
padding: 1rem;
|
padding: 2.5rem;
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
margin-top: 1rem;
|
|
||||||
font-size: 1.5rem;
|
font-size: 1.5rem;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.subtitle {
|
.subtitle {
|
||||||
margin-top: 1rem;
|
|
||||||
color: $second-text-color;
|
|
||||||
font-size: 1.3rem;
|
font-size: 1.3rem;
|
||||||
|
|
||||||
|
&.gray {
|
||||||
|
color: $second-text-color;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.footer {
|
.footer {
|
||||||
height: 4rem;
|
height: 4.6rem;
|
||||||
margin-top: 2rem;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
border-top: 1px solid whitesmoke;
|
border-top: 1px solid whitesmoke;
|
||||||
font-size: 1.4rem;
|
font-size: 1.4rem;
|
||||||
@ -93,9 +119,16 @@ export default {
|
|||||||
width: 49%;
|
width: 49%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ok {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
.cancel {
|
.cancel {
|
||||||
color: $second-text-color;
|
|
||||||
border-right: 1px solid whitesmoke;
|
border-right: 1px solid whitesmoke;
|
||||||
|
|
||||||
|
&.gray {
|
||||||
|
color: $second-text-color;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
115
src/components/dialog/NoticeDialog.vue
Normal file
115
src/components/dialog/NoticeDialog.vue
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
<template>
|
||||||
|
<div class="NoticeDialog" @click="$emit('dismiss')">
|
||||||
|
<div class="content" @click.stop="null">
|
||||||
|
<div class="body">
|
||||||
|
<div class="title">{{ title }}</div>
|
||||||
|
<div class="subtitle" :class="subtitleColor" v-if="subtitle">{{ subtitle }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="footer">
|
||||||
|
<div class="cancel" @click.stop="$emit('cancel')">{{ cancelText }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: "NoticeDialog",
|
||||||
|
props: {
|
||||||
|
visible: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
default() {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
subtitle: {
|
||||||
|
type: String,
|
||||||
|
default() {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
subtitleColor: {
|
||||||
|
type: String,
|
||||||
|
default() {
|
||||||
|
return 'gray'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
cancelText: {
|
||||||
|
type: String,
|
||||||
|
default() {
|
||||||
|
return '取消'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
@import "../../assets/scss/index";
|
||||||
|
|
||||||
|
.NoticeDialog {
|
||||||
|
z-index: 10;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
background: #000000bb;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
color: black;
|
||||||
|
|
||||||
|
|
||||||
|
.content {
|
||||||
|
background: white;
|
||||||
|
width: 70%;
|
||||||
|
border-radius: 2px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
.body {
|
||||||
|
padding: 2.5rem;
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subtitle {
|
||||||
|
margin-top: 1rem;
|
||||||
|
font-size: 1.3rem;
|
||||||
|
|
||||||
|
&.gray{
|
||||||
|
color: $second-text-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
height: 4.6rem;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
border-top: 1px solid whitesmoke;
|
||||||
|
font-size: 1.4rem;
|
||||||
|
|
||||||
|
|
||||||
|
.cancel {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
</style>
|
||||||
36
src/pages/login/Base.js
Normal file
36
src/pages/login/Base.js
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
export default {
|
||||||
|
name: "Base",
|
||||||
|
props: {},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
isAgree: false,
|
||||||
|
isOtherLogin: false,
|
||||||
|
showAnim: false,
|
||||||
|
showTooltip: false,
|
||||||
|
loading: false,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {},
|
||||||
|
created() {
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async check() {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
if (this.isAgree) {
|
||||||
|
resolve(true)
|
||||||
|
} else {
|
||||||
|
if (!this.showAnim && !this.showTooltip) {
|
||||||
|
this.showAnim = true
|
||||||
|
setTimeout(() => {
|
||||||
|
this.showAnim = false
|
||||||
|
this.showTooltip = true
|
||||||
|
}, 500)
|
||||||
|
setTimeout(() => {
|
||||||
|
this.showTooltip = false
|
||||||
|
}, 3000)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
56
src/pages/login/Base.scss
Normal file
56
src/pages/login/Base.scss
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
@import "../../assets/scss/index";
|
||||||
|
|
||||||
|
.content {
|
||||||
|
padding: 6rem 3rem;
|
||||||
|
//padding-top: 6rem;
|
||||||
|
|
||||||
|
.desc {
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
margin-top: 4rem;
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 2rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sub-title {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
color: $second-text-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.notice {
|
||||||
|
margin-top: 1rem;
|
||||||
|
font-size: 1.3rem;
|
||||||
|
color: $primary-btn-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
margin-bottom: .5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.protocol {
|
||||||
|
position: relative;
|
||||||
|
color: gray;
|
||||||
|
margin-top: 2rem;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
.left {
|
||||||
|
padding-top: .1rem;
|
||||||
|
margin-right: .5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.options {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
margin-top: 2rem;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
<LoginInput autofocus type="phone" v-model="phone" placeholder="请输入手机号"/>
|
<LoginInput autofocus type="phone" v-model="phone" placeholder="请输入手机号"/>
|
||||||
|
|
||||||
<div class="notice">
|
<div class="notice" v-if="notice">
|
||||||
{{ notice }}
|
{{ notice }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -47,9 +47,11 @@
|
|||||||
import Check from "../../components/Check";
|
import Check from "../../components/Check";
|
||||||
import Tooltip from "./components/Tooltip";
|
import Tooltip from "./components/Tooltip";
|
||||||
import LoginInput from "./components/LoginInput";
|
import LoginInput from "./components/LoginInput";
|
||||||
|
import Base from "./Base.js";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "OtherLogin",
|
name: "OtherLogin",
|
||||||
|
extends: Base,
|
||||||
components: {
|
components: {
|
||||||
Check,
|
Check,
|
||||||
Tooltip,
|
Tooltip,
|
||||||
@ -57,12 +59,7 @@ export default {
|
|||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
isAgree: false,
|
|
||||||
phone: '',
|
phone: '',
|
||||||
isOtherLogin: false,
|
|
||||||
showAnim: false,
|
|
||||||
showTooltip: false,
|
|
||||||
loading: false,
|
|
||||||
notice: ''
|
notice: ''
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -70,23 +67,13 @@ export default {
|
|||||||
created() {
|
created() {
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
getCode() {
|
async getCode() {
|
||||||
if (this.isAgree) {
|
let res = await this.check()
|
||||||
|
if (res){
|
||||||
this.loading = true
|
this.loading = true
|
||||||
setTimeout(()=>{
|
setTimeout(() => {
|
||||||
this.$nav('/login/verification-code')
|
this.$nav('/login/verification-code')
|
||||||
},2000)
|
}, 2000)
|
||||||
} else {
|
|
||||||
if (!this.showAnim && !this.showTooltip) {
|
|
||||||
this.showAnim = true
|
|
||||||
setTimeout(() => {
|
|
||||||
this.showAnim = false
|
|
||||||
this.showTooltip = true
|
|
||||||
}, 500)
|
|
||||||
setTimeout(() => {
|
|
||||||
this.showTooltip = false
|
|
||||||
}, 3000)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -95,6 +82,7 @@ export default {
|
|||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
@import "../../assets/scss/index";
|
@import "../../assets/scss/index";
|
||||||
|
@import "Base.scss";
|
||||||
|
|
||||||
.other-login {
|
.other-login {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
@ -107,58 +95,5 @@ export default {
|
|||||||
font-size: 1.4rem;
|
font-size: 1.4rem;
|
||||||
background: white;
|
background: white;
|
||||||
|
|
||||||
.content {
|
|
||||||
padding: 6rem 3rem;
|
|
||||||
//padding-top: 6rem;
|
|
||||||
|
|
||||||
.desc {
|
|
||||||
margin-bottom: 2rem;
|
|
||||||
margin-top: 4rem;
|
|
||||||
display: flex;
|
|
||||||
align-items: flex-start;
|
|
||||||
flex-direction: column;
|
|
||||||
|
|
||||||
.title {
|
|
||||||
font-size: 2rem;
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sub-title {
|
|
||||||
font-size: 1.2rem;
|
|
||||||
color: $second-text-color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.notice {
|
|
||||||
margin-top: 1rem;
|
|
||||||
font-size: 1.3rem;
|
|
||||||
color: $primary-btn-color;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button {
|
|
||||||
margin-bottom: .5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.protocol {
|
|
||||||
position: relative;
|
|
||||||
color: gray;
|
|
||||||
margin-top: 2rem;
|
|
||||||
margin-bottom: 2rem;
|
|
||||||
font-size: 1.2rem;
|
|
||||||
display: flex;
|
|
||||||
|
|
||||||
.left {
|
|
||||||
padding-top: .1rem;
|
|
||||||
margin-right: .5rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.options {
|
|
||||||
font-size: 1.2rem;
|
|
||||||
margin-top: 2rem;
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -6,14 +6,15 @@
|
|||||||
</template>
|
</template>
|
||||||
</BaseHeader>
|
</BaseHeader>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<div class="notice">
|
<div class="desc">
|
||||||
<div class="title">手机号密码登录</div>
|
<div class="title">手机号密码登录</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<LoginInput autofocus type="phone" v-model="phone" placeholder="请输入手机号"/>
|
<LoginInput autofocus type="phone" v-model="phone" placeholder="请输入手机号"/>
|
||||||
<LoginInput autofocus class="mt1r" type="password" v-model="password" placeholder="请输入密码"/>
|
<LoginInput autofocus class="mt1r" type="password" v-model="password" placeholder="请输入密码"/>
|
||||||
|
|
||||||
<div class="protocol">
|
<div class="protocol" :class="showAnim?'anim-bounce':''">
|
||||||
|
<Tooltip style="top: -150%;left: -1rem;" v-model="showTooltip"/>
|
||||||
<div class="left">
|
<div class="left">
|
||||||
<Check v-model="isAgree"/>
|
<Check v-model="isAgree"/>
|
||||||
</div>
|
</div>
|
||||||
@ -26,13 +27,17 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="notice" v-if="notice">
|
||||||
|
{{ notice }}
|
||||||
|
</div>
|
||||||
|
|
||||||
<b-button :loading="loading" :active="false" :disabled="disabled" @click="login">
|
<b-button :loading="loading" :active="false" :disabled="disabled" @click="login">
|
||||||
{{ loading ? '登录中' : '登录' }}
|
{{ loading ? '登录中' : '登录' }}
|
||||||
</b-button>
|
</b-button>
|
||||||
|
|
||||||
<div class="options">
|
<div class="options">
|
||||||
<span>
|
<span>
|
||||||
忘记了?<span class="link">找回密码</span>
|
忘记了?<span class="link" @click="$nav('/login/retrieve-password')">找回密码</span>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -42,22 +47,23 @@
|
|||||||
<script>
|
<script>
|
||||||
import Check from "../../components/Check";
|
import Check from "../../components/Check";
|
||||||
import LoginInput from "./components/LoginInput";
|
import LoginInput from "./components/LoginInput";
|
||||||
|
import Tooltip from "./components/Tooltip";
|
||||||
|
import Base from "./Base";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "PasswordLogin",
|
name: "PasswordLogin",
|
||||||
|
extends: Base,
|
||||||
components: {
|
components: {
|
||||||
Check,
|
Check,
|
||||||
|
Tooltip,
|
||||||
LoginInput
|
LoginInput
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
isAgree: false,
|
|
||||||
showAnim: false,
|
|
||||||
showTooltip: false,
|
|
||||||
loading: false,
|
|
||||||
phone: '',
|
phone: '',
|
||||||
password: '',
|
password: '',
|
||||||
code: '',
|
code: '',
|
||||||
|
notice: '',
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@ -68,20 +74,10 @@ export default {
|
|||||||
created() {
|
created() {
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
login() {
|
async login() {
|
||||||
if (this.isAgree) {
|
let res = await this.check()
|
||||||
|
if (res) {
|
||||||
this.loading = true
|
this.loading = true
|
||||||
} else {
|
|
||||||
if (!this.showAnim && !this.showTooltip) {
|
|
||||||
this.showAnim = true
|
|
||||||
setTimeout(() => {
|
|
||||||
this.showAnim = false
|
|
||||||
this.showTooltip = true
|
|
||||||
}, 500)
|
|
||||||
setTimeout(() => {
|
|
||||||
this.showTooltip = false
|
|
||||||
}, 3000)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -90,6 +86,7 @@ export default {
|
|||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
@import "../../assets/scss/index";
|
@import "../../assets/scss/index";
|
||||||
|
@import "Base.scss";
|
||||||
|
|
||||||
.PasswordLogin {
|
.PasswordLogin {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
@ -102,51 +99,5 @@ export default {
|
|||||||
font-size: 1.4rem;
|
font-size: 1.4rem;
|
||||||
background: white;
|
background: white;
|
||||||
|
|
||||||
.content {
|
|
||||||
padding: 6rem 3rem;
|
|
||||||
//padding-top: 6rem;
|
|
||||||
|
|
||||||
.notice {
|
|
||||||
margin-bottom: 2rem;
|
|
||||||
margin-top: 4rem;
|
|
||||||
display: flex;
|
|
||||||
align-items: flex-start;
|
|
||||||
flex-direction: column;
|
|
||||||
|
|
||||||
.title {
|
|
||||||
font-size: 2rem;
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sub-title {
|
|
||||||
font-size: 1.2rem;
|
|
||||||
color: $second-text-color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.button {
|
|
||||||
margin-bottom: .5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.protocol {
|
|
||||||
color: gray;
|
|
||||||
margin-top: 2rem;
|
|
||||||
margin-bottom: 2rem;
|
|
||||||
font-size: 1.2rem;
|
|
||||||
display: flex;
|
|
||||||
|
|
||||||
.left {
|
|
||||||
padding-top: .1rem;
|
|
||||||
margin-right: .5rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.options {
|
|
||||||
font-size: 1.2rem;
|
|
||||||
margin-top: 2rem;
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
147
src/pages/login/RetrievePassword.vue
Normal file
147
src/pages/login/RetrievePassword.vue
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
<template>
|
||||||
|
<div class="RetrievePassword">
|
||||||
|
<BaseHeader mode="light" :isClose="true"></BaseHeader>
|
||||||
|
<div class="content">
|
||||||
|
<div class="desc">
|
||||||
|
<div class="title">找回密码</div>
|
||||||
|
<div class="sub-title">验证码已通过短信发送到+86 13800138000。
|
||||||
|
密码为8 - 20位,至少包含字母、数字、符号2种组合
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<LoginInput
|
||||||
|
autofocus
|
||||||
|
type="code"
|
||||||
|
v-model="code"
|
||||||
|
placeholder="请输入验证码"
|
||||||
|
v-model:isSendVerificationCode="isSendVerificationCode"
|
||||||
|
@send="sendCode"
|
||||||
|
/>
|
||||||
|
<LoginInput
|
||||||
|
class="mt1r"
|
||||||
|
autofocus
|
||||||
|
type="password"
|
||||||
|
v-model="password"
|
||||||
|
placeholder="请输入密码"
|
||||||
|
/>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="protocol" :class="showAnim?'anim-bounce':''">
|
||||||
|
<Tooltip style="top: -150%;left: -1rem;" v-model="showTooltip"/>
|
||||||
|
<div class="left">
|
||||||
|
<Check v-model="isAgree"/>
|
||||||
|
</div>
|
||||||
|
<div class="right">
|
||||||
|
已阅读并同意
|
||||||
|
<span class="link" @click="$nav('/service-protocol',{type:'“抖音”用户服务协议'})">用户协议</span>
|
||||||
|
和
|
||||||
|
<span class="link" @click="$nav('/service-protocol',{type:'“抖音”隐私政策'})">隐私政策</span>
|
||||||
|
,同时登录并使用抖音火山版(原“火山小视频”)和抖音
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="notice" v-if="notice">
|
||||||
|
{{ notice }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<b-button
|
||||||
|
:loading="loading"
|
||||||
|
:active="false"
|
||||||
|
:loadingWithText="true"
|
||||||
|
:disabled="disabled"
|
||||||
|
@click="login">
|
||||||
|
完成
|
||||||
|
</b-button>
|
||||||
|
|
||||||
|
<div class="options" v-if="showVoiceCode">
|
||||||
|
<span>
|
||||||
|
收不到短信?<span class="link" @click="getVoiceCode">获取语音验证码</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import Check from "../../components/Check";
|
||||||
|
import LoginInput from "./components/LoginInput";
|
||||||
|
import Tooltip from "./components/Tooltip";
|
||||||
|
import Base from "./Base";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "RetrievePassword",
|
||||||
|
extends: Base,
|
||||||
|
components: {
|
||||||
|
Check,
|
||||||
|
Tooltip,
|
||||||
|
LoginInput,
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
phone: '',
|
||||||
|
password: '',
|
||||||
|
code: '',
|
||||||
|
notice: '',
|
||||||
|
isSendVerificationCode: true,
|
||||||
|
showVoiceCode: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
disabled() {
|
||||||
|
return !(this.code && this.password);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
setTimeout(() => {
|
||||||
|
this.showVoiceCode = true
|
||||||
|
}, 3000)
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getVoiceCode() {
|
||||||
|
return this.$showNoticeDialog('语音验证码',
|
||||||
|
'我们将以电话的方式告知你验证码,请注意接听',
|
||||||
|
'',
|
||||||
|
() => {
|
||||||
|
setTimeout(() => {
|
||||||
|
this.$showConfirmDialog('', '您的手机可能由于空号/欠费/停机无法收到验证码,请恢复手机号状态,如果' +
|
||||||
|
'您因为换号无法收到验证码,可以尝试找回账号', '', () => {
|
||||||
|
}, null, '找回账号', '返回', '')
|
||||||
|
}, 2000)
|
||||||
|
},
|
||||||
|
'知道了'
|
||||||
|
)
|
||||||
|
},
|
||||||
|
//TODO loading样式不对
|
||||||
|
async sendCode() {
|
||||||
|
this.$showLoading()
|
||||||
|
await this.$sleep(500)
|
||||||
|
this.$hideLoading()
|
||||||
|
this.isSendVerificationCode = true
|
||||||
|
},
|
||||||
|
async login() {
|
||||||
|
let res = await this.check()
|
||||||
|
if (res) {
|
||||||
|
this.loading = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
@import "../../assets/scss/index";
|
||||||
|
@import "Base.scss";
|
||||||
|
|
||||||
|
.RetrievePassword {
|
||||||
|
position: fixed;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
top: 0;
|
||||||
|
overflow: auto;
|
||||||
|
color: black;
|
||||||
|
font-size: 1.4rem;
|
||||||
|
background: white;
|
||||||
|
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -6,7 +6,7 @@
|
|||||||
</template>
|
</template>
|
||||||
</BaseHeader>
|
</BaseHeader>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<div class="notice">
|
<div class="desc">
|
||||||
<div class="title">请输入验证码</div>
|
<div class="title">请输入验证码</div>
|
||||||
<div class="sub-title">验证码已通过短信发送到+86 13800138000</div>
|
<div class="sub-title">验证码已通过短信发送到+86 13800138000</div>
|
||||||
</div>
|
</div>
|
||||||
@ -17,7 +17,7 @@
|
|||||||
v-model:isSendVerificationCode="isSendVerificationCode"
|
v-model:isSendVerificationCode="isSendVerificationCode"
|
||||||
@send="sendCode"
|
@send="sendCode"
|
||||||
/>
|
/>
|
||||||
<div class="options">
|
<div class="options" v-if="showVoiceCode">
|
||||||
<span>
|
<span>
|
||||||
收不到短信?<span class="link" @click="getVoiceCode">获取语音验证码</span>
|
收不到短信?<span class="link" @click="getVoiceCode">获取语音验证码</span>
|
||||||
</span>
|
</span>
|
||||||
@ -27,21 +27,18 @@
|
|||||||
{{ loading ? '登录中' : '登录' }}
|
{{ loading ? '登录中' : '登录' }}
|
||||||
</b-button>
|
</b-button>
|
||||||
|
|
||||||
<!-- <ConfirmDialog></ConfirmDialog>-->
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import Check from "../../components/Check";
|
import Check from "../../components/Check";
|
||||||
import LoginInput from "./components/LoginInput";
|
import LoginInput from "./components/LoginInput";
|
||||||
import ConfirmDialog from "../../components/dialog/ConfirmDialog";
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "VerificationCode",
|
name: "VerificationCode",
|
||||||
components: {
|
components: {
|
||||||
Check,
|
Check,
|
||||||
LoginInput,
|
LoginInput,
|
||||||
ConfirmDialog
|
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@ -52,13 +49,28 @@ export default {
|
|||||||
password: '',
|
password: '',
|
||||||
code: '',
|
code: '',
|
||||||
isSendVerificationCode: true,
|
isSendVerificationCode: true,
|
||||||
|
showVoiceCode: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
|
setTimeout(() => {
|
||||||
|
this.showVoiceCode = true
|
||||||
|
}, 3000)
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
getVoiceCode(){
|
getVoiceCode() {
|
||||||
this.$showConfirmDialog('','语音验证码')
|
return this.$showNoticeDialog('语音验证码',
|
||||||
|
'我们将以电话的方式告知你验证码,请注意接听',
|
||||||
|
'',
|
||||||
|
() => {
|
||||||
|
setTimeout(() => {
|
||||||
|
this.$showConfirmDialog('', '您的手机可能由于空号/欠费/停机无法收到验证码,请恢复手机号状态,如果' +
|
||||||
|
'您因为换号无法收到验证码,可以尝试找回账号', '', () => {
|
||||||
|
}, null, '找回账号', '返回', '')
|
||||||
|
}, 2000)
|
||||||
|
},
|
||||||
|
'知道了'
|
||||||
|
)
|
||||||
},
|
},
|
||||||
//TODO loading样式不对
|
//TODO loading样式不对
|
||||||
async sendCode() {
|
async sendCode() {
|
||||||
@ -80,6 +92,7 @@ export default {
|
|||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
@import "../../assets/scss/index";
|
@import "../../assets/scss/index";
|
||||||
|
@import "Base.scss";
|
||||||
|
|
||||||
.VerificationCode {
|
.VerificationCode {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
@ -92,39 +105,13 @@ export default {
|
|||||||
font-size: 1.4rem;
|
font-size: 1.4rem;
|
||||||
background: white;
|
background: white;
|
||||||
|
|
||||||
.content {
|
.options{
|
||||||
padding: 6rem 3rem;
|
margin-top: 1rem;
|
||||||
//padding-top: 6rem;
|
|
||||||
|
|
||||||
.notice {
|
|
||||||
margin-bottom: 2rem;
|
|
||||||
margin-top: 4rem;
|
|
||||||
display: flex;
|
|
||||||
align-items: flex-start;
|
|
||||||
flex-direction: column;
|
|
||||||
|
|
||||||
.title {
|
|
||||||
font-size: 2rem;
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sub-title {
|
|
||||||
font-size: 1.2rem;
|
|
||||||
color: $second-text-color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.button {
|
|
||||||
margin-bottom: .5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.options {
|
|
||||||
font-size: 1.2rem;
|
|
||||||
margin-top: 2rem;
|
|
||||||
margin-bottom: 2rem;
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.button{
|
||||||
|
margin-top: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -6,20 +6,39 @@
|
|||||||
<div class="arrow"></div>
|
<div class="arrow"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="right flex1">
|
<div class="right flex1">
|
||||||
<input :autofocus="autofocus" v-model="value" type="text" :placeholder="placeholder">
|
<input
|
||||||
<img v-if="value" src="../../../assets/img/icon/login/close-full-gray.png" alt="" @click="value=''">
|
@click="isTyping = true"
|
||||||
|
@blur="delaySetTypingFalse"
|
||||||
|
:autofocus="autofocus"
|
||||||
|
v-model="value"
|
||||||
|
type="text"
|
||||||
|
:placeholder="placeholder">
|
||||||
|
<img v-if="value && isTyping" src="../../../assets/img/icon/login/close-full-gray.png" alt="" @click="value=''">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="input-number" v-if="type === 'password'">
|
<div class="input-number" v-if="type === 'password'">
|
||||||
<div class="right flex1">
|
<div class="right flex1">
|
||||||
<input :autofocus="autofocus" v-model="value" type="password" :placeholder="placeholder">
|
<input
|
||||||
<img v-if="value" src="../../../assets/img/icon/login/close-full-gray.png" alt="" @click="value=''">
|
@click="isTyping = true"
|
||||||
|
@blur="delaySetTypingFalse"
|
||||||
|
:autofocus="autofocus"
|
||||||
|
v-model="value"
|
||||||
|
type="password"
|
||||||
|
autocomplete="new-password"
|
||||||
|
:placeholder="placeholder">
|
||||||
|
<img v-if="value && isTyping" src="../../../assets/img/icon/login/close-full-gray.png" alt="" @click="value=''">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="input-number" v-if="type === 'code'">
|
<div class="input-number" v-if="type === 'code'">
|
||||||
<div class="left no-border flex1">
|
<div class="left no-border flex1">
|
||||||
<input :autofocus="autofocus" v-model="value" type="text" :placeholder="placeholder">
|
<input
|
||||||
<img v-if="value" src="../../../assets/img/icon/login/close-full-gray.png" alt="" @click="value=''">
|
@click="isTyping = true"
|
||||||
|
@blur="delaySetTypingFalse"
|
||||||
|
:autofocus="autofocus"
|
||||||
|
v-model="value"
|
||||||
|
type="text"
|
||||||
|
:placeholder="placeholder">
|
||||||
|
<img v-if="value && isTyping" src="../../../assets/img/icon/login/close-full-gray.png" alt="" @click="value=''">
|
||||||
</div>
|
</div>
|
||||||
<div class="right" @click="send">
|
<div class="right" @click="send">
|
||||||
<span :class="isSendVerificationCode && 'disabled'">{{ verificationCodeBtnText }}</span>
|
<span :class="isSendVerificationCode && 'disabled'">{{ verificationCodeBtnText }}</span>
|
||||||
@ -48,6 +67,7 @@ export default {
|
|||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
isTyping: false,
|
||||||
verificationCodeBtnText: 60
|
verificationCodeBtnText: 60
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -81,8 +101,13 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
send(){
|
delaySetTypingFalse() {
|
||||||
if (!this.isSendVerificationCode){
|
setTimeout(() => {
|
||||||
|
this.isTyping = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
send() {
|
||||||
|
if (!this.isSendVerificationCode) {
|
||||||
this.$emit('send')
|
this.$emit('send')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -174,6 +199,10 @@ export default {
|
|||||||
border: none;
|
border: none;
|
||||||
background: whitesmoke;
|
background: whitesmoke;
|
||||||
caret-color: red;
|
caret-color: red;
|
||||||
|
|
||||||
|
&[type="password"] {
|
||||||
|
//letter-spacing: 1rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -54,7 +54,7 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
clear() {
|
clear() {
|
||||||
this.$showConfirmDialog('确定清空?', '清空后,以往观看记录不再展示', () => {
|
this.$showConfirmDialog('确定清空?', '清空后,以往观看记录不再展示', 'gray',() => {
|
||||||
this.list = 0
|
this.list = 0
|
||||||
console.log(this.list)
|
console.log(this.list)
|
||||||
})
|
})
|
||||||
|
|||||||
@ -40,6 +40,7 @@ import Login from "../pages/login/Login";
|
|||||||
import OtherLogin from "../pages/login/OtherLogin";
|
import OtherLogin from "../pages/login/OtherLogin";
|
||||||
import PasswordLogin from "../pages/login/PasswordLogin";
|
import PasswordLogin from "../pages/login/PasswordLogin";
|
||||||
import VerificationCode from "../pages/login/VerificationCode";
|
import VerificationCode from "../pages/login/VerificationCode";
|
||||||
|
import RetrievePassword from "../pages/login/RetrievePassword";
|
||||||
|
|
||||||
const routes = [
|
const routes = [
|
||||||
// {path: '', component: Music},
|
// {path: '', component: Music},
|
||||||
@ -84,6 +85,7 @@ const routes = [
|
|||||||
{path: '/login/other', component: OtherLogin},
|
{path: '/login/other', component: OtherLogin},
|
||||||
{path: '/login/password', component: PasswordLogin},
|
{path: '/login/password', component: PasswordLogin},
|
||||||
{path: '/login/verification-code', component: VerificationCode},
|
{path: '/login/verification-code', component: VerificationCode},
|
||||||
|
{path: '/login/retrieve-password', component: RetrievePassword},
|
||||||
]
|
]
|
||||||
|
|
||||||
export default VueRouter.createRouter({
|
export default VueRouter.createRouter({
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import SimpleConfirmDialog from "../components/dialog/SimpleConfirmDialog";
|
|||||||
import ConfirmDialog from "../components/dialog/ConfirmDialog";
|
import ConfirmDialog from "../components/dialog/ConfirmDialog";
|
||||||
import Loading from "../components/Loading";
|
import Loading from "../components/Loading";
|
||||||
import Config from '../config'
|
import Config from '../config'
|
||||||
|
import NoticeDialog from "../components/dialog/NoticeDialog";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
$showLoading() {
|
$showLoading() {
|
||||||
@ -69,7 +70,7 @@ export default {
|
|||||||
document.body.append(parent)
|
document.body.append(parent)
|
||||||
app.mount(parent)
|
app.mount(parent)
|
||||||
},
|
},
|
||||||
$showConfirmDialog(title, subtitle, okCb, cancelCb) {
|
$showConfirmDialog(title, subtitle, subtitleColor, okCb, cancelCb, okText, cancelText, cancelTextColor) {
|
||||||
let remove = () => {
|
let remove = () => {
|
||||||
let parent = document.querySelector('.dialog-ctn')
|
let parent = document.querySelector('.dialog-ctn')
|
||||||
parent.classList.replace('fade-in', 'fade-out')
|
parent.classList.replace('fade-in', 'fade-out')
|
||||||
@ -79,11 +80,11 @@ export default {
|
|||||||
}
|
}
|
||||||
let tempOkCb = e => {
|
let tempOkCb = e => {
|
||||||
remove()
|
remove()
|
||||||
okCb(e)
|
okCb && okCb(e)
|
||||||
}
|
}
|
||||||
let tempCancelCb = e => {
|
let tempCancelCb = e => {
|
||||||
remove()
|
remove()
|
||||||
cancelCb(e)
|
cancelCb && cancelCb(e)
|
||||||
}
|
}
|
||||||
const app = Vue.createApp({
|
const app = Vue.createApp({
|
||||||
render() {
|
render() {
|
||||||
@ -91,6 +92,10 @@ export default {
|
|||||||
onDismiss={remove}
|
onDismiss={remove}
|
||||||
title={title}
|
title={title}
|
||||||
subtitle={subtitle}
|
subtitle={subtitle}
|
||||||
|
subtitleColor={subtitleColor}
|
||||||
|
cancelTextColor={cancelTextColor}
|
||||||
|
okText={okText}
|
||||||
|
cancelText={cancelText}
|
||||||
onOk={tempOkCb}/>
|
onOk={tempOkCb}/>
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@ -99,6 +104,33 @@ export default {
|
|||||||
document.body.append(parent)
|
document.body.append(parent)
|
||||||
app.mount(parent)
|
app.mount(parent)
|
||||||
},
|
},
|
||||||
|
$showNoticeDialog(title, subtitle, subtitleColor, cancelCb, cancelText) {
|
||||||
|
let remove = () => {
|
||||||
|
let parent = document.querySelector('.dialog-ctn')
|
||||||
|
parent.classList.replace('fade-in', 'fade-out')
|
||||||
|
setTimeout(() => {
|
||||||
|
parent.remove()
|
||||||
|
}, 300)
|
||||||
|
}
|
||||||
|
let tempCancelCb = e => {
|
||||||
|
remove()
|
||||||
|
cancelCb(e)
|
||||||
|
}
|
||||||
|
const app = Vue.createApp({
|
||||||
|
render() {
|
||||||
|
return <NoticeDialog onCancel={tempCancelCb}
|
||||||
|
onDismiss={remove}
|
||||||
|
title={title}
|
||||||
|
subtitleColor={subtitleColor}
|
||||||
|
cancelText={cancelText}
|
||||||
|
subtitle={subtitle}/>
|
||||||
|
},
|
||||||
|
})
|
||||||
|
let parent = document.createElement('div')
|
||||||
|
parent.classList.add(...['dialog-ctn', 'fade-in'])
|
||||||
|
document.body.append(parent)
|
||||||
|
app.mount(parent)
|
||||||
|
},
|
||||||
$notice(val) {
|
$notice(val) {
|
||||||
let div = document.createElement('div')
|
let div = document.createElement('div')
|
||||||
div.classList.add('global-notice')
|
div.classList.add('global-notice')
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user