119 lines
2.0 KiB
Vue
119 lines
2.0 KiB
Vue
|
|
<template>
|
||
|
|
<view class="code-box">
|
||
|
|
<view
|
||
|
|
v-for="(item, idx) in codeLength"
|
||
|
|
:key="idx"
|
||
|
|
:class="['code-cell', idx === currentIndex ? 'active' : '', code[idx] ? 'filled' : '']">
|
||
|
|
<text v-if="code[idx]">{{ code[idx] }}</text>
|
||
|
|
</view>
|
||
|
|
<!-- 隐藏真实输入框 -->
|
||
|
|
<input
|
||
|
|
class="real-input"
|
||
|
|
type="number"
|
||
|
|
:maxlength="codeLength"
|
||
|
|
v-model="inputValue"
|
||
|
|
:focus="true"
|
||
|
|
@input="onInput"
|
||
|
|
@focus="onFocus"
|
||
|
|
@blur="onBlur"
|
||
|
|
cursor-spacing="100"
|
||
|
|
ref="realInput" />
|
||
|
|
</view>
|
||
|
|
</template>
|
||
|
|
|
||
|
|
<script>
|
||
|
|
export default {
|
||
|
|
name:"input-box",
|
||
|
|
props: {
|
||
|
|
codeLength: {
|
||
|
|
type: Number,
|
||
|
|
default: 4
|
||
|
|
}
|
||
|
|
},
|
||
|
|
data() {
|
||
|
|
return {
|
||
|
|
inputValue: '',
|
||
|
|
};
|
||
|
|
},
|
||
|
|
computed: {
|
||
|
|
code() {
|
||
|
|
return this.inputValue.split('').slice(0, this.codeLength)
|
||
|
|
},
|
||
|
|
currentIndex() {
|
||
|
|
return this.inputValue.length
|
||
|
|
}
|
||
|
|
},
|
||
|
|
methods: {
|
||
|
|
onInput(e) {
|
||
|
|
let val = e.detail.value.replace(/[^0-9]/g, '').slice(0, this.codeLength)
|
||
|
|
this.inputValue = val
|
||
|
|
this.$emit('input', val)
|
||
|
|
if (val.length === this.codeLength) {
|
||
|
|
this.$emit('confirm', val)
|
||
|
|
}
|
||
|
|
},
|
||
|
|
onFocus() {
|
||
|
|
this.isFocus = true
|
||
|
|
this.inputValue = ''
|
||
|
|
},
|
||
|
|
onBlur() {
|
||
|
|
this.isFocus = false
|
||
|
|
},
|
||
|
|
onConfirm() {
|
||
|
|
if (this.inputValue.length === this.codeLength) {
|
||
|
|
this.$emit('confirm', this.inputValue);
|
||
|
|
}
|
||
|
|
},
|
||
|
|
close() {
|
||
|
|
this.$emit('close')
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
</script>
|
||
|
|
|
||
|
|
<style lang="scss" scoped>
|
||
|
|
.code-box {
|
||
|
|
flex-direction: row;
|
||
|
|
display: flex;
|
||
|
|
justify-content: center;
|
||
|
|
margin-bottom: 48rpx;
|
||
|
|
position: relative;
|
||
|
|
|
||
|
|
.code-cell {
|
||
|
|
width: 72rpx;
|
||
|
|
height: 72rpx;
|
||
|
|
border: 2rpx solid #eee;
|
||
|
|
border-radius: 16rpx;
|
||
|
|
margin-right: 24rpx;
|
||
|
|
font-size: 40rpx;
|
||
|
|
color: #ff4d8d;
|
||
|
|
background: #fff;
|
||
|
|
text-align: center;
|
||
|
|
line-height: 72rpx;
|
||
|
|
box-sizing: border-box;
|
||
|
|
transition: border-color 0.2s;
|
||
|
|
|
||
|
|
&.active {
|
||
|
|
border-color: #ff4d8d;
|
||
|
|
}
|
||
|
|
|
||
|
|
&.filled {
|
||
|
|
border-color: #ff4d8d;
|
||
|
|
}
|
||
|
|
|
||
|
|
&:last-child {
|
||
|
|
margin-right: 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
.real-input {
|
||
|
|
position: absolute;
|
||
|
|
left: 0;
|
||
|
|
top: 0;
|
||
|
|
width: 100%;
|
||
|
|
height: 100%;
|
||
|
|
opacity: 0;
|
||
|
|
z-index: 2;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
</style>
|