mand-mobile/components/captcha/index.vue

261 lines
5.7 KiB
Vue
Raw Normal View History

2018-03-26 16:04:04 +08:00
<template>
<div class="md-captcha" v-show="isView || value || visible">
<template v-if="isView">
<div class="md-captcha-content">
<h2 class="md-captcha-title" v-if="title" v-text="title"></h2>
2018-04-11 15:22:40 +08:00
<div class="md-captcha-error" v-text="errorMsg"></div>
<div class="md-captcha-message">
2018-03-26 16:04:04 +08:00
<slot></slot>
</div>
<md-button
v-if="count"
class="md-captcha-countbtn"
2018-03-26 16:04:04 +08:00
type="ghost"
size="small"
v-text="countBtnText"
2018-03-26 16:04:04 +08:00
:disabled="this.isCounting"
@click="$_onResend"
2018-03-26 16:04:04 +08:00
></md-button>
</div>
<md-codebox
ref="codebox"
v-model="code"
:maxlength="maxlength"
:system="system"
:closable="false"
:isView="isView"
:mask="mask"
:autofocus="false"
@submit="$_onSubmit"
/>
</template>
<template v-else>
<md-dialog
:value="value"
:closable="true"
:appendTo="false"
position="center"
@input="$_onInput"
@show="$_onShow"
@hide="$_onHide"
>
<div class="md-captcha-content">
<h2 class="md-captcha-title" v-if="title" v-text="title"></h2>
2018-04-11 15:22:40 +08:00
<div class="md-captcha-error" v-text="errorMsg"></div>
<div class="md-captcha-message">
2018-03-26 16:04:04 +08:00
<slot></slot>
</div>
<md-button
v-if="count"
class="md-captcha-countbtn"
2018-03-26 16:04:04 +08:00
type="ghost"
size="small"
v-text="countBtnText"
2018-03-26 16:04:04 +08:00
:disabled="this.isCounting"
@click="$_onResend"
2018-03-26 16:04:04 +08:00
></md-button>
</div>
<md-codebox
ref="codebox"
v-model="code"
:maxlength="maxlength"
:system="system"
:closable="false"
:mask="mask"
:autofocus="false"
@submit="$_onSubmit"
/>
</md-dialog>
</template>
</div>
</template>
<script> import Dialog from '../dialog'
import Codebox from '../codebox'
import Button from '../button'
export default {
name: 'md-captcha',
components: {
[Dialog.name]: Dialog,
[Codebox.name]: Codebox,
[Button.name]: Button,
},
props: {
title: {
type: String,
},
value: {
type: Boolean,
default: false,
},
maxlength: {
type: [Number, String],
default: 4,
},
mask: {
type: Boolean,
default: false,
},
system: {
type: Boolean,
default: false,
},
autoCountdown: {
type: Boolean,
default: true,
},
2018-03-26 16:04:04 +08:00
appendTo: {
default: () => document.body,
},
count: {
type: Number,
default: 60,
},
countNormalText: {
type: String,
default: '发送验证码',
},
countActiveText: {
type: String,
default: '{$1}秒后重发',
},
2018-03-26 16:04:04 +08:00
isView: {
type: Boolean,
default: false,
},
},
data() {
return {
code: '',
visible: false,
2018-04-11 15:22:40 +08:00
errorMsg: '',
2018-03-26 16:04:04 +08:00
isCounting: false,
firstShown: false,
countBtnText: this.countNormalText,
2018-03-26 16:04:04 +08:00
}
},
watch: {
value(val) {
if (val) {
this.code = ''
if (!this.firstShown) {
this.firstShown = true
this.$_onResend()
2018-03-26 16:04:04 +08:00
}
}
},
2018-04-11 15:22:40 +08:00
code(val) {
if (val && this.errorMsg) {
this.errorMsg = ''
}
},
2018-03-26 16:04:04 +08:00
},
mounted() {
if (this.appendTo && !this.isView) {
this.appendTo.appendChild(this.$el)
}
if (this.value || this.isView) {
2018-03-26 16:04:04 +08:00
this.firstShown = true
this.$_onResend()
2018-03-26 16:04:04 +08:00
}
},
2018-04-18 15:05:47 +08:00
beforeDestroy() {
if (this.appendTo && !this.isView) {
this.appendTo.removeChild(this.$el)
}
},
2018-03-26 16:04:04 +08:00
methods: {
// MARK: events handler, 如 $_onButtonClick
$_onInput(val) {
this.$emit('input', val)
},
$_onShow() {
this.visible = true
this.$refs.codebox.focus()
this.$emit('show')
},
$_onHide() {
this.visible = false
this.$refs.codebox.blur()
this.$emit('hide')
},
$_onSubmit(code) {
this.$emit('submit', code)
},
$_onResend() {
if (this.autoCountdown) {
this.countdown()
}
this.$emit('send', this.countdown)
2018-03-26 16:04:04 +08:00
},
// MARK: public methods
countdown() {
2018-04-24 22:49:00 +08:00
if (!this.count) {
return
}
2018-03-26 16:04:04 +08:00
clearInterval(this.__counter__)
let i = this.count - 1
this.isCounting = true
this.countBtnText = this.countActiveText.replace('{$1}', i)
2018-04-23 17:33:32 +08:00
/* istanbul ignore next */
2018-03-26 16:04:04 +08:00
this.__counter__ = setInterval(() => {
if (i === 1) {
2018-03-26 16:04:04 +08:00
this.resetcount()
} else {
i--
this.countBtnText = this.countActiveText.replace('{$1}', i)
2018-03-26 16:04:04 +08:00
}
}, 1000)
},
resetcount() {
this.isCounting = false
this.countBtnText = this.countNormalText
2018-03-26 16:04:04 +08:00
clearInterval(this.__counter__)
},
2018-04-11 15:22:40 +08:00
setError(msg) {
this.$nextTick(() => {
this.errorMsg = msg
this.code = ''
})
},
2018-03-26 16:04:04 +08:00
},
}
</script>
<style lang="stylus">
.md-captcha
.md-dialog
z-index captcha-zindex
.md-dialog-content
margin-bottom number-keyboard-height
2018-03-26 16:04:04 +08:00
.md-captcha-content
text-align center
margin-bottom 20px
font-size 24px
.md-captcha-title
color captcha-title-color
font-size captcha-title-font-size
2018-04-11 15:22:40 +08:00
margin 0
.md-captcha-error
color captcha-error-color
2018-04-11 15:22:40 +08:00
font-size 24px
line-height 32px
height 32px
margin-bottom 12px
.md-captcha-countbtn
display inline-block
padding-left 16px
padding-right 16px
margin captcha-countbtn-gap auto
width auto
min-width 130px
2018-03-26 16:04:04 +08:00
</style>