17 changed files with 596 additions and 150 deletions
After Width: | Height: | Size: 9.8 KiB |
After Width: | Height: | Size: 7.6 KiB |
After Width: | Height: | Size: 3.4 KiB |
After Width: | Height: | Size: 6.7 KiB |
After Width: | Height: | Size: 8.3 KiB |
@ -0,0 +1,138 @@
@@ -0,0 +1,138 @@
|
||||
<template> |
||||
<div class="button" :class="class1" @click.capture.stop="check"> |
||||
<img v-if="loading" src="../assets/img/icon/loading-white.png" alt=""> |
||||
<slot v-if="showText"></slot> |
||||
</div> |
||||
</template> |
||||
<script> |
||||
export default { |
||||
name: "BaseButton", |
||||
props: { |
||||
loading: { |
||||
type: Boolean, |
||||
default: false |
||||
}, |
||||
loadingWithText: { |
||||
type: Boolean, |
||||
default: false |
||||
}, |
||||
disabled: { |
||||
type: Boolean, |
||||
default: false |
||||
}, |
||||
type: { |
||||
type: String, |
||||
default: 'primary' |
||||
}, |
||||
active: { |
||||
type: Boolean, |
||||
default: true |
||||
}, |
||||
}, |
||||
data() { |
||||
return {} |
||||
}, |
||||
computed: { |
||||
class1() { |
||||
return [this.type, this.active ? '' : 'no-active', this.disabled && 'disabled'] |
||||
}, |
||||
showText() { |
||||
if (this.loading) { |
||||
return this.loadingWithText |
||||
} |
||||
return true |
||||
} |
||||
}, |
||||
created() { |
||||
}, |
||||
methods: { |
||||
check() { |
||||
if (this.disabled) return |
||||
if (this.loading) return |
||||
return this.$emit('click') |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style scoped lang="scss"> |
||||
@import "../assets/scss/index"; |
||||
|
||||
.button { |
||||
color: white; |
||||
height: 4rem; |
||||
line-height: 4rem; |
||||
border-radius: .3rem; |
||||
//width: 100%; |
||||
font-size: 1.4rem; |
||||
display: flex; |
||||
justify-content: center; |
||||
align-items: center; |
||||
|
||||
img { |
||||
height: 1.6rem; |
||||
margin-right: .5rem; |
||||
animation: animal .8s infinite linear; |
||||
|
||||
@keyframes animal { |
||||
0% { |
||||
transform: rotate(-360deg); |
||||
} |
||||
100% { |
||||
transform: rotate(0deg); |
||||
} |
||||
} |
||||
} |
||||
|
||||
&.primary { |
||||
background: $primary-btn-color; |
||||
|
||||
&:active { |
||||
background: $disable-primary-btn-color; |
||||
} |
||||
} |
||||
|
||||
&.no-active { |
||||
&:active { |
||||
&.primary { |
||||
background: $primary-btn-color; |
||||
} |
||||
|
||||
&.dark { |
||||
background: $second-btn-color; |
||||
} |
||||
|
||||
&.white { |
||||
background: white; |
||||
} |
||||
} |
||||
} |
||||
|
||||
&.disabled { |
||||
&.primary { |
||||
background: gainsboro; |
||||
color: white; |
||||
} |
||||
|
||||
&:active { |
||||
&.primary { |
||||
background: gainsboro; |
||||
} |
||||
} |
||||
} |
||||
|
||||
&.dark { |
||||
background: $second-btn-color; |
||||
|
||||
&:active { |
||||
background: $second-btn-color-tran; |
||||
} |
||||
} |
||||
|
||||
&.white { |
||||
background: white; |
||||
color: black; |
||||
border: 1px solid gainsboro; |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,130 @@
@@ -0,0 +1,130 @@
|
||||
<template> |
||||
<div class="VerificationCode"> |
||||
<BaseHeader mode="light" :isClose="true"> |
||||
<template v-slot:right> |
||||
<span class="f16">帮助</span> |
||||
</template> |
||||
</BaseHeader> |
||||
<div class="content"> |
||||
<div class="notice"> |
||||
<div class="title">请输入验证码</div> |
||||
<div class="sub-title">验证码已通过短信发送到+86 13800138000</div> |
||||
</div> |
||||
|
||||
<LoginInput autofocus type="code" |
||||
v-model="code" |
||||
placeholder="请输入验证码" |
||||
v-model:isSendVerificationCode="isSendVerificationCode" |
||||
@send="sendCode" |
||||
/> |
||||
<div class="options"> |
||||
<span> |
||||
收不到短信?<span class="link" @click="getVoiceCode">获取语音验证码</span> |
||||
</span> |
||||
</div> |
||||
|
||||
<b-button :loading="loading" :active="false" :disabled="code.length < 4" @click="login"> |
||||
{{ loading ? '登录中' : '登录' }} |
||||
</b-button> |
||||
|
||||
<!-- <ConfirmDialog></ConfirmDialog>--> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
<script> |
||||
import Check from "../../components/Check"; |
||||
import LoginInput from "./components/LoginInput"; |
||||
import ConfirmDialog from "../../components/dialog/ConfirmDialog"; |
||||
|
||||
export default { |
||||
name: "VerificationCode", |
||||
components: { |
||||
Check, |
||||
LoginInput, |
||||
ConfirmDialog |
||||
}, |
||||
data() { |
||||
return { |
||||
showAnim: false, |
||||
showTooltip: false, |
||||
loading: false, |
||||
phone: '', |
||||
password: '', |
||||
code: '', |
||||
isSendVerificationCode: true, |
||||
} |
||||
}, |
||||
created() { |
||||
}, |
||||
methods: { |
||||
getVoiceCode(){ |
||||
this.$showConfirmDialog('','语音验证码') |
||||
}, |
||||
//TODO loading样式不对 |
||||
async sendCode() { |
||||
this.$showLoading() |
||||
await this.$sleep(500) |
||||
this.$hideLoading() |
||||
this.isSendVerificationCode = true |
||||
}, |
||||
login() { |
||||
this.loading = true |
||||
setTimeout(() => { |
||||
this.isSendVerificationCode = true |
||||
this.loading = false |
||||
}, 1000) |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style scoped lang="scss"> |
||||
@import "../../assets/scss/index"; |
||||
|
||||
.VerificationCode { |
||||
position: fixed; |
||||
left: 0; |
||||
right: 0; |
||||
bottom: 0; |
||||
top: 0; |
||||
overflow: auto; |
||||
color: black; |
||||
font-size: 1.4rem; |
||||
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; |
||||
} |
||||
|
||||
.options { |
||||
font-size: 1.2rem; |
||||
margin-top: 2rem; |
||||
margin-bottom: 2rem; |
||||
display: flex; |
||||
justify-content: space-between; |
||||
} |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,179 @@
@@ -0,0 +1,179 @@
|
||||
<template> |
||||
<div> |
||||
<div class="input-number" v-if="type === 'phone'"> |
||||
<div class="left"> |
||||
<span>+86</span> |
||||
<div class="arrow"></div> |
||||
</div> |
||||
<div class="right flex1"> |
||||
<input :autofocus="autofocus" v-model="value" type="text" :placeholder="placeholder"> |
||||
<img v-if="value" src="../../../assets/img/icon/login/close-full-gray.png" alt="" @click="value=''"> |
||||
</div> |
||||
</div> |
||||
<div class="input-number" v-if="type === 'password'"> |
||||
<div class="right flex1"> |
||||
<input :autofocus="autofocus" v-model="value" type="password" :placeholder="placeholder"> |
||||
<img v-if="value" src="../../../assets/img/icon/login/close-full-gray.png" alt="" @click="value=''"> |
||||
</div> |
||||
</div> |
||||
<div class="input-number" v-if="type === 'code'"> |
||||
<div class="left no-border flex1"> |
||||
<input :autofocus="autofocus" v-model="value" type="text" :placeholder="placeholder"> |
||||
<img v-if="value" src="../../../assets/img/icon/login/close-full-gray.png" alt="" @click="value=''"> |
||||
</div> |
||||
<div class="right" @click="send"> |
||||
<span :class="isSendVerificationCode && 'disabled'">{{ verificationCodeBtnText }}</span> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
<script> |
||||
export default { |
||||
name: "LoginInput", |
||||
props: { |
||||
modelValue: '', |
||||
placeholder: '', |
||||
type: { |
||||
type: String, |
||||
default: 'phone' |
||||
}, |
||||
autofocus: { |
||||
type: Boolean, |
||||
default: false |
||||
}, |
||||
isSendVerificationCode: { |
||||
type: Boolean, |
||||
default: false |
||||
}, |
||||
}, |
||||
data() { |
||||
return { |
||||
verificationCodeBtnText: 60 |
||||
} |
||||
}, |
||||
computed: { |
||||
value: { |
||||
get() { |
||||
return this.modelValue |
||||
}, |
||||
set(e) { |
||||
this.$emit('update:modelValue', e) |
||||
} |
||||
} |
||||
}, |
||||
watch: { |
||||
isSendVerificationCode: { |
||||
immediate: true, |
||||
handler(newVal, oldVal) { |
||||
if (newVal) { |
||||
this.verificationCodeBtnText = 60 |
||||
let ticker = setInterval(() => { |
||||
if (this.verificationCodeBtnText > 0) { |
||||
this.verificationCodeBtnText-- |
||||
} else { |
||||
this.verificationCodeBtnText = '重新发送' |
||||
this.$emit('update:isSendVerificationCode', false) |
||||
clearInterval(ticker) |
||||
} |
||||
}, 1000) |
||||
} |
||||
} |
||||
} |
||||
}, |
||||
methods: { |
||||
send(){ |
||||
if (!this.isSendVerificationCode){ |
||||
this.$emit('send') |
||||
} |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style scoped lang="scss"> |
||||
@import "../../../assets/scss/index"; |
||||
|
||||
.input-number { |
||||
display: flex; |
||||
background: whitesmoke; |
||||
padding: 1.5rem 1rem; |
||||
font-size: 1.4rem; |
||||
|
||||
.left { |
||||
display: flex; |
||||
align-items: center; |
||||
margin-right: 1rem; |
||||
padding-right: 1rem; |
||||
position: relative; |
||||
|
||||
&.no-border { |
||||
&::before { |
||||
content: ''; |
||||
display: none; |
||||
} |
||||
} |
||||
|
||||
&.flex1 { |
||||
flex: 1; |
||||
margin-right: 0; |
||||
padding-right: 0; |
||||
} |
||||
|
||||
img { |
||||
top: 50%; |
||||
transform: translateY(-50%); |
||||
right: 1rem; |
||||
position: absolute; |
||||
height: 1.5rem; |
||||
} |
||||
|
||||
.arrow { |
||||
margin-top: .4rem; |
||||
margin-left: .5rem; |
||||
width: 0; |
||||
height: 0; |
||||
border: .3rem solid transparent; |
||||
border-top: .5rem solid black; |
||||
} |
||||
|
||||
&::before { |
||||
content: ' '; |
||||
position: absolute; |
||||
width: 1px; |
||||
height: .8rem; |
||||
top: 4px; |
||||
right: 0; |
||||
background: gainsboro; |
||||
} |
||||
} |
||||
|
||||
.right { |
||||
//background: red; |
||||
position: relative; |
||||
|
||||
&.flex1 { |
||||
flex: 1; |
||||
} |
||||
|
||||
img { |
||||
top: 50%; |
||||
transform: translateY(-50%); |
||||
right: 1rem; |
||||
position: absolute; |
||||
height: 1.5rem; |
||||
} |
||||
|
||||
.disabled { |
||||
color: $second-text-color; |
||||
} |
||||
} |
||||
|
||||
input { |
||||
width: 90%; |
||||
outline: none; |
||||
border: none; |
||||
background: whitesmoke; |
||||
caret-color: red; |
||||
} |
||||
} |
||||
</style> |
Loading…
Reference in new issue