mand-mobile/components/captcha/index.vue

298 lines
6.5 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-message">
2018-03-26 16:04:04 +08:00
<slot></slot>
</div>
</div>
<md-codebox
ref="codebox"
v-model="code"
:maxlength="maxlength"
:system="system"
:mask="mask"
@submit="$_onSubmit"
2018-08-27 19:17:20 +08:00
:closable="false"
:isView="true"
:justify="true"
:autofocus="false"
2018-09-14 16:03:24 +08:00
>
<footer class="md-captcha-footer">
2018-11-15 15:47:44 +08:00
<div class="md-captcha-error" v-if="errorMsg" v-text="errorMsg"></div>
<div class="md-captcha-brief" v-else v-text="brief"></div>
2018-09-14 16:03:24 +08:00
<button
class="md-captcha-btn"
v-if="count"
v-text="countBtnText"
:disabled="this.isCounting"
@click="$_onResend"
></button>
</footer>
</md-codebox>
2018-03-26 16:04:04 +08:00
</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-message">
2018-03-26 16:04:04 +08:00
<slot></slot>
</div>
</div>
<md-codebox
ref="codebox"
v-model="code"
:maxlength="maxlength"
:system="system"
:closable="false"
:mask="mask"
2018-08-27 19:17:20 +08:00
:justify="true"
2018-03-26 16:04:04 +08:00
:autofocus="false"
@submit="$_onSubmit"
2018-09-14 16:03:24 +08:00
>
<footer class="md-captcha-footer">
2018-11-15 15:47:44 +08:00
<div class="md-captcha-error" v-if="errorMsg" v-text="errorMsg"></div>
<div class="md-captcha-brief" v-else v-text="brief"></div>
2018-09-14 16:03:24 +08:00
<button
class="md-captcha-btn"
v-if="count"
v-text="countBtnText"
:disabled="this.isCounting"
@click="$_onResend"
></button>
</footer>
</md-codebox>
2018-03-26 16:04:04 +08:00
</md-dialog>
</template>
</div>
</template>
<script> import Dialog from '../dialog'
import Codebox from '../codebox'
import Button from '../button'
import {mdDocument} from '../_util'
2018-03-26 16:04:04 +08:00
export default {
name: 'md-captcha',
components: {
[Dialog.name]: Dialog,
[Codebox.name]: Codebox,
[Button.name]: Button,
},
props: {
title: {
type: String,
},
2018-11-15 15:47:44 +08:00
brief: {
type: String,
default: '',
},
2018-03-26 16:04:04 +08:00
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: () => mdDocument.body,
2018-03-26 16:04:04 +08:00
},
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__)
const timestamp = Date.now()
let i = this.count
2018-03-26 16:04:04 +08:00
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.count - Math.floor((Date.now() - timestamp) / 1000)
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-04-11 15:22:40 +08:00
})
},
2018-03-26 16:04:04 +08:00
},
}
</script>
<style lang="stylus">
2018-08-27 19:17:20 +08:00
.md-captcha
.md-dialog
2018-11-11 12:17:35 +08:00
.md-popup
z-index captcha-zindex
2018-08-27 19:17:20 +08:00
.md-dialog-body
2018-09-14 16:03:24 +08:00
padding 60px 60px 30px 60px
2018-08-27 19:17:20 +08:00
.md-dialog-content
margin-bottom number-keyboard-height
2018-09-14 16:03:24 +08:00
.md-codebox
margin-bottom 28px
2018-08-27 19:17:20 +08:00
.md-captcha-content
font-size captcha-font-size
color captcha-color
text-align center
line-height 1.2
margin-bottom 50px
.md-captcha-title
color captcha-title-color
font-size captcha-title-font-size
font-weight normal
line-height 1.15
margin 0 0 16px 0
.md-captcha-footer
2018-09-14 16:03:24 +08:00
margin 28px 0
2018-08-27 19:17:20 +08:00
display flex
font-size captcha-footer-font-size
justify-content space-between
align-items center
overflow hidden
2018-11-15 15:47:44 +08:00
.md-captcha-error, .md-captcha-brief
2018-08-27 19:17:20 +08:00
flex 1 1 0%
2018-11-15 15:47:44 +08:00
.md-captcha-error
2018-08-27 19:17:20 +08:00
color captcha-error-color
2018-11-15 15:47:44 +08:00
.md-captcha-brief
color captcha-brief-color
2018-08-27 19:17:20 +08:00
.md-captcha-btn
display inline-block
color captcha-btn-color
font-size captcha-footer-font-size
padding 0
margin 0 0 0 12px
border 0
border-radius 0
background none
&:disabled
color color-text-disabled
2018-03-26 16:04:04 +08:00
</style>