微信小程序验证码登录(获取手机号&倒计时)实现

功能逻辑:

点击手机号输入框时,首先唤醒【获取手机号授权】,若用户授权则赋值(可修改),若用户拒绝授权则手动输入;

点击获取验证码后,倒计时重新获取;

若输入错误,给出校验提示语;

 

注意:

获取手机号授权的功能是需要花钱认证的,要在小程序后台支付300块~

 

wxml:

<!--components/captchaLogin/captchaLogin.wxml-->
<view class="captchaLogin-wrip {{hidden? 'captchaLogin-wrip-hidden':'captchaLogin-wrip-show'}}">
  <!-- 手机号 -->
  <view class="captchaLogin-captcha">
    <input class="captchaLogin-input" type="number" placeholder="请输入手机号码" value="{{phone}}" placeholder-class="captchaLogin-input-placeholder" bindinput="bindPhone" />
    <button wx:if="{{firstLaunch}}" open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber" class="phone-button" style="width: 100%;"></button>
  </view>
  <!-- 验证码 -->
  <view class="captchaLogin-captcha">
    <view class="captchaLogin-inputLine">
      <input class="captchaLogin-input" type="number" placeholder="请输入验证码" placeholder-class="captchaLogin-input-placeholder" bindinput="bindCaptcha" maxlength="8" />
      <view class="captchaLogin-btn {{!canGetCaptcha ? 'captchaLogin-btn-disabled' : ''}}" bindtap="getCaptcha">{{captchaText}}</view>
    </view>
  </view>
  <mp-toptips msg="{{error}}" type="error" show="{{error}}"></mp-toptips>
</view>

  

js:

// components/captchaLogin/captchaLogin.js
const app = getApp();

Component({
  /**
   * 组件的属性列表
   */
  properties: {
    hidden: {
      type: Boolean,
      value: true
    }
  },

  /**
   * 组件的初始数据
   */
  data: {
    phone: '',
    code: '',
    error: '',
    canGetCaptcha: true,
    captchaText: '获取验证码',
    firstLaunch: true, // 是否是第一次进入(用于控制是否获取手机号授权)
  },
  // lifetimes: {
  //   created: function () {
  //     console.log('...created')
  //   },
  // },
  /**
   * 组件的方法列表
   */
  methods: {
    //获取微信用户手机号
    getPhoneNumber(e) {
      console.log(e.detail, '===detail')
      if (e.detail.errMsg === 'getPhoneNumber:ok') {
        this.getPhone({
          wx_code: e.detail.code
        })
      }
      //   if (e.detail.errMsg === "getPhoneNumber:fail user deny") {
      //     wx.showModal({
      //         title: '提示',
      //         content: '您已拒绝授权',
      //         showCancel: false,
      //         confirmText: "知道了"
      //     })
      // }
      this.setData({
        firstLaunch: false
      })
    },
    getPhone: function (params) {
      const that = this;
      wx.request({
        url: app.apiInfo.host + '/vip/index/getPhone',
        method: 'GET',
        data: params,
        header: {
          'content-type': 'application/json' // 默认值
        },
        success(res) {
          if (res?.data?.code === 0) {
            that.setData({
              phone: res?.data?.data?.phone || ''
            })
          } else {
            wx.showToast({
              title: res?.data?.msg || '获取失败',
              icon: 'error',
              duration: 3000
            })
          }
        },
        complete() {
          wx.hideLoading()
        }
      })
    },
    bindPhone: function (e) {
      const {
        code
      } = this.data;
      this.setData({
        phone: e.detail.value
      })
      const pattern = /^((1)[0-9]{10})?$/;
      if (!pattern.test(e.detail.value)) {
        return;
      } else {
        this.triggerEvent('captchaLoginData', {
          phone: e.detail.value,
          code
        })
      }
    },
    bindCaptcha: function (e) {
      const {
        phone
      } = this.data;
      // 验证码去空格
      const str = e.detail.value?.replaceAll(" ", "")
      this.setData({
        code: str
      })
      const pattern = /^((1)[0-9]{10})?$/;
      if (!phone || (phone && !pattern.test(phone))) {
        return;
      } else {
        this.triggerEvent('captchaLoginData', {
          code: str,
          phone
        })
      }
    },
    // 验证码倒计时
    getCaptchaCode: function (e) {
      var that = this;
      var num = 120;
      // 修改验证码发送状态及文案
      that.setData({
        canGetCaptcha: false,
        captchaText: `${num}s后重新获取`
      });
      var timer = setInterval(function () {
        num--;
        if (num <= 0) {
          clearInterval(timer)
          that.setData({
            canGetCaptcha: true,
            captchaText: '获取验证码'
          });
        } else {
          that.setData({
            canGetCaptcha: false,
            captchaText: `${num}s后重新获取`
          });
        }
      }, 1000)
    },
    // 发送验证码
    sendSms: function (params) {
      wx.showLoading({
        title: '验证码发送中',
        mask: true
      })
      const that = this;
      wx.request({
        url: app.apiInfo.host + '/vip/index/sendSms',
        method: 'POST',
        data: params,
        header: {
          'content-type': 'application/json' // 默认值
        },
        success(res) {
          // 验证码发送成功,开始倒计时
          if (res?.data?.code === 0) {
            wx.showToast({
              title: res?.data?.msg || '发送成功',
              icon: 'success',
              duration: 3000
            })
            that.getCaptchaCode()
          } else {
            wx.showToast({
              title: res?.data?.msg || '操作失败',
              icon: 'error',
              duration: 3000
            })
          }
        },
        complete() {
          wx.hideLoading()
        }
      })
    },
    // 获取验证码-按钮点击事件
    getCaptcha: function () {
      const {
        phone,
        canGetCaptcha
      } = this.data;
      // 验证码可发
      if (canGetCaptcha) {
        const pattern = /^((1)[0-9]{10})?$/;
        if (!phone || !pattern.test(phone)) {
          this.setData({
            error: '请输入正确手机号'
          })
          return false;
        }
        // 发送验证码
        console.log('===发送验证码')
        this.sendSms({
          phone
        })
      } else {
        return false;
      }
    },
  }
})

 

json:

{
  "component": true,
  "usingComponents": {
    "mp-toptips": "weui-miniprogram/toptips/toptips"
  }
}

  

wxss:

/* components/captchaLogin/captchaLogin.wxss */
.captchaLogin-wrip-hidden {
  display: none;
}

.captchaLogin-wrip-show {
  display: block;
}

.captchaLogin-captcha {
  position: relative;
  width: 100%;
  padding: 16rpx 80rpx;
  box-sizing: border-box;
  z-index: 0;
}

.captchaLogin-input {
  display: inline-block;
  width: 100%;
  border: 2rpx solid #ffd6a3;
  height: 88rpx;
  text-align: left;
  padding-left: 36rpx;
  box-sizing: border-box;
  border-radius: 4rpx;
}

.captchaLogin-input-placeholder {
  color: #b2b1b1;
  text-align: left;
  font-size: 28rpx;
  padding-left: 4rpx;
}

.captchaLogin-inputLine {
  position: relative;
}

.captchaLogin-btn {
  position: absolute;
  right: 0;
  top: 0;
  bottom: 0;
  width: 200rpx;
  display: block;
  height: 88rpx;
  line-height: 88rpx;
  font-size: 24rpx;
  text-align: center;
  color: #ed7543;
  z-index: 2;
}

.captchaLogin-btn-disabled {
  color: #eea88a;
}
.phone-button{
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 2;
  background-color: transparent;
}

  

主页面获取用户输入的数据:

 <view>
        <captchaLogin bind:captchaLoginData="getLoginData"  hidden="{{ activeKey === '1' }}"/>
        <pwdLogin bind:captchaLoginData="getLoginData" hidden="{{ activeKey === '0' }}"/>
      </view>


 // 获取登录所需数据
  getLoginData(e) {
    this.setData({
      loginData: e.detail
    })
  },

  

posted @ 2023-03-17 16:42  芝麻小仙女  阅读(1490)  评论(0)    收藏  举报