效果图
代码实现
< view>
< view class = " tips" >
已发送验证码至
< text class = " tips-phone" > {{ phoneNumber }}</ text>
</ view>
< view class = " code-input-wrap" >
< input class = " code-input" v-model = " codeNumber" type = " number" :adjust-position = " false" :auto-blur = " true" maxlength = " 6" @input = " handleInputClick" />
< view class = " code-list" >
< block v-for = " (item, index) in 6" :key = " index" >
< view :class = " ['code-list-item', codeNumber.length == index ? 'active-item' : '']" > {{ codeNumber[index] }}</ view>
</ block>
</ view>
</ view>
< view class = " resending" v-if = " isSending" > {{ '重新发送(' + counter + 's)' }}</ view>
< view class = " normal" v-else @click = " handleResend" > 重新发送</ view>
</ view>
data ( ) {
return {
phoneNumber : '' ,
codeNumber : '' ,
isPhoneValid : false ,
isCodeValid : false ,
isSending : false ,
timer : null ,
counter : 60
}
} ,
methods : {
handleInputClick ( e ) {
let val = e. detail. value
this . codeNumber = val
if ( val && val. length == 6 ) {
this . isCodeValid = true
} else {
this . isCodeValid = false
}
} ,
sendSmsCode ( ) {
if ( this . isPhoneValid) {
if ( ! / ^1[3456789]\d{9}$ / . test ( this . phoneNumber) ) {
uni. showToast ( {
title : '手机号格式不正确' ,
icon : 'none'
} )
return false
}
if ( ! this . isChecked) {
this . showTips = true
return false
}
}
} ,
countDown ( ) {
this . counter = 60
this . isSending = true
this . timer = setInterval ( ( ) => {
this . counter--
if ( this . counter < 0 ) {
this . reset ( )
}
} , 1000 )
} ,
reset ( ) {
this . isSending = false
if ( this . timer) {
clearInterval ( this . timer)
this . counter = 60
this . timer = null
}
} ,
handleResend ( ) {
this . codeNumber = ''
this . sendSmsCode ( )
}
}
.tips {
font-size : 28rpx;
font-weight : 400;
line-height : 36rpx;
.tips-phone {
font-weight : bold;
margin-left : 20rpx;
}
}
// 验证码输入
.code-input-wrap {
margin : 40rpx 0;
position : relative;
height : 100rpx;
.code-input {
position : absolute;
left : 0;
top : 0;
height : 100rpx;
width : 100%;
opacity : 0;
z-index : 99;
outline : none;
}
.code-list {
position : absolute;
left : 0;
top : 0;
width : 100%;
height : 100rpx;
display : flex;
justify-content : space-between;
.code-list-item {
// flex : 1;
width : 90rpx;
height : 100rpx;
background : #ffffff;
border-radius : 16rpx;
font-size : 36rpx;
font-weight : 700;
color : #adb3ba;
line-height : 100rpx;
text-align : center;
margin-right : 10rpx;
z-index : 5;
box-sizing : border-box;
}
.code-list-item:last-child {
margin-right : 0;
}
.active-item {
border : 2rpx solid #ff466d;
}
}
}
.resending {
font-size : 28rpx;
font-weight : 500;
line-height : 36rpx;
margin-bottom : 60rpx;
color : #a6acb2;
}
.normal {
font-size : 28rpx;
font-weight : 500;
line-height : 36rpx;
margin-bottom : 60rpx;
color : #333;
}