[uniapp]登录注册案例

2024年8月21日 15:59 by wst

小程序

功能

登陆注册是一个系统最基本的功能,今天花了一点时间把这个两个功能实现了。

1.登陆方式为手机号登陆,可以密码登录或者验证码登录;

2.验证码发送完60秒内不能在发送第二次;

3.只有前端部分的实现,开发框架为uniapp;

代码

登录

<template>
  <view class="content">
    <view class="topBox">
      <view class="tit">
        欢迎登陆
      </view>
      <view class="desc">
        没有账号?
        <navigator
          url="/pages/register/register"
          open-type="navigate"
          hover-class="navigator-hover"
        >
        去注册
        </navigator>
      </view>
    </view>

    <view class="bottomBox">
      <view class="item">
        <view class="label">
          账号
        </view>
        <input type="text" v-model="phone" placeholder="请输入您的手机号码" />
      </view>
      <view class="item" v-if="login_type==1">
        <view class="label">
          密码
        </view>
        <input type="password" v-model="password" placeholder="请输入您的密码" />
      </view>
      <view class="item" v-if="login_type==2">
        <view class="label">
          验证码
        </view>
        <view class="yzmBox">
          <input type="text" v-model="checkcode" placeholder="请输入验证码" />
          <view class="yzm" @click="send">
            {{ login_VerifyCode }}
          </view>
        </view>
      </view>
      <button type="default" @click="submit">登陆</button>
    </view>
    <view class="agree" v-if="login_type==1">
      <text>忘记密码?采用验</text>
      <view class="protocol" @click="changeType">证码登陆</view>
    </view>
  </view>
</template>

<script setup>
import { ref } from 'vue';

const phone = ref();
const password = ref();
const checkcode = ref();
const login_type = ref(1);  // 默认密码登陆
const login_VerifyCode = ref("获取验证码"); //发送验证码按钮显示文字
const login_timer = ref(false); //验证码计时器
const timer = ref();        // 计时器

function send() {
  // 检测输入-手机号
  var {flag, msg} = checkPhone(phone.value)
  if(!flag){
    uni.showToast({
      title: msg,
      icon: "error"
    })
    return false
  }
  if(login_VerifyCode.value == '获取验证码' || login_VerifyCode.value == '重新发送'){
    // todo 发送验证码给后台
    let code = 1;
    if(code == 1){
      uni.showToast({
        title: "发送验证码"
      })
      login_timer.value = true
      var total_micro_second = 60;
      // 验证码倒计时
      count_down(total_micro_second);
    } else {
      uni.showToast({
        title: "发送错误",
        icon: "error"
      })
    }
  }

}

/**
 * 倒计时 验证码
 * @param {*} total_micro_second
 * @returns
 */
function count_down(total_micro_second) { //发送验证码按钮
    if (total_micro_second <= 0) {
        login_VerifyCode.value = "重新发送"
        // timeout则跳出递归
        return false;
    } else {
        // 渲染倒计时时钟
        login_VerifyCode.value = total_micro_second + "s"
        total_micro_second--;
        if (login_timer.value == true) {
            timer = setTimeout(function () {
                count_down(total_micro_second);
            }, 1000)
        } else {
            login_VerifyCode.value = "获取验证码"
        }
    }
}

function checkPhone(val) {
  if (!/^1((34[0-8])|(8\d{2})|(([35][0-35-9]|4[579]|66|7[35678]|9[1389])\d{1}))\d{7}$/.test(val)) {
    return {flag:false, msg:"请输入正确的手机号"}
  } else {
    return {flag: true, msg: "手机号正确"}
  }
}

function checkPassword(val){
  var pwdRegex = new RegExp('(?=.*[0-9])(?=.*[a-zA-Z]).{8,30}');
  if(!pwdRegex.test(val)){
    return {flag: false, msg: '您的密码复杂度太低(密码中必须包含字母、数字),请及时修改密码!'}
  } else {
    return {flag: true, msg: "密码格式正确"}
  }
}

function checkInputCode(val){
  var checkRegex = new RegExp('[0-9]{6}');
  if(!checkRegex.test(val)){
    return {flag: false, msg: '验证码错误'}
  } else {
    return {flag: true, msg: "验证码格式正确"}
  }
}

function submit() {
  console.log("phone:", phone.value, "password:", password.value, "checkcode:", checkcode.value)
  // 检测输入-手机号
  var {flag, msg} = checkPhone(phone.value)
  if(!flag){
    uni.showToast({
      title: msg,
      icon: "error"
    })
    return false
  }
  // 检测输入-密码
  var {flag, msg} = checkPassword(password.value)
  if(!flag){
    uni.showToast({
      title: msg,
      icon: "error"
    })
    return false
  }
  // 检测输入-验证码
  var {flag, msg} = checkInputCode(checkcode.value)
  if(!flag){
    uni.showToast({
      title: msg,
      icon: "error"
    })
    return false
  }
  // 提交给后台 todo

  console.log("submit success")
  uni.navigateTo({
    url:"/pages/register/register"
  })

}

/**修改登陆类型 */
function changeType(){
  login_type.value = 2; // 验证码登陆
}


</script>

<style lang="scss" scoped>
  .content {
    min-height: 100vh;
  }

  .topBox {
    position: relative;
    height: 400rpx;
    background-color: #00aaff;
  }

  .tit {
    width: 90%;
    font-size: 60rpx;
    color: #ffffff;
    position: absolute;
    bottom: 40%;
    left: 50%;
    transform: translateX(-50%);
    font-weight: 600;
  }

  .desc {
    width: 90%;
    font-size: 30rpx;
    color: #f8f8f8;
    position: absolute;
    bottom: 25%;
    left: 50%;
    transform: translateX(-50%);
    display: flex;
    navigator {
      font-weight: 800;
    }
  }

  .bottomBox {
    margin-top: 20rpx;
    min-height: 500rpx;
    padding: 50rpx;
  }

  .item {
    margin-bottom: 60rpx;
    border-bottom: 1px solid #ccc;
  }

  .item .label {
    font-size: 32rpx;
    color: #00aaff;
    font-weight: 600;
    margin-bottom: 20rpx;
  }

  .item input {
    height: 70rpx;
    padding-bottom: 20rpx;
    font-size: 32rpx;
    color: #333;
  }

  .uni-input-placeholder {
    color: #bebebe;
  }

  .yzmBox {
    display: flex;
    justify-content: space-between;
    align-items: center;
  }

  .yzm {
    color: #ffffff;
    font-size: 28rpx;
    padding: 5rpx 8rpx;
    background-color: #00aaff;
  }

  button {
    line-height: 85rpx;
    text-align: center;
    background: rgb(0, 170, 255);
    color: #fff;
    margin-top: 100rpx;
  }

  .agree {
    position: fixed;
    bottom: 60rpx;
    left: 20%;
    text-align: center;
    width: 100%;
    color: #919191;
    font-size: 30rpx;
    display: flex;
    .protocol{
      color: #00aaff;
    }
  }

</style>

      

注册

<template>
  <view class="content">
    <view class="topBox">
      <view class="tit">
        新用户注册
      </view>
      <view class="desc">
        已有账号?
        <navigator
          url="/pages/login/login"
          open-type="navigate"
          hover-class="navigator-hover"
        >
          去登录
        </navigator>
      </view>
    </view>

    <view class="bottomBox">
      <view class="item">
        <view class="label">
          账号
        </view>
        <input type="text" v-model="phone" placeholder="请输入您的手机号码" />
      </view>
      <view class="item">
        <view class="label">
          密码
        </view>
        <input type="password" v-model="password" placeholder="请输入您的密码" />
      </view>
      <view class="item">
        <view class="label">
          验证码
        </view>
        <view class="yzmBox">
          <input type="text" v-model="checkcode" placeholder="请输入验证码" />
          <view class="yzm" @click="send">
            {{ login_VerifyCode }}
          </view>
        </view>
      </view>
      <button type="default" @click="submit">注册</button>
    </view>
    <view class="agree">
      注册代表您同意
      <text class="protocol">用户隐私协议</text>
    </view>
  </view>
</template>

<script setup>
import { ref } from 'vue';

const phone = ref();
const password = ref();
const checkcode = ref();
const login_VerifyCode = ref("获取验证码"); //发送验证码按钮显示文字
const login_timer = ref(false); //验证码计时器
const timer = ref();        // 计时器


function send() {
  // 检测输入-手机号
  var {flag, msg} = checkPhone(phone.value)
  if(!flag){
    uni.showToast({
      title: msg,
      icon: "error"
    })
    return false
  }
  if(login_VerifyCode.value == '获取验证码' || login_VerifyCode.value == '重新发送'){
    // todo 发送验证码给后台
    let code = 1;
    if(code == 1){
      uni.showToast({
        title: "发送验证码"
      })
      login_timer.value = true
      var total_micro_second = 60;
      // 验证码倒计时
      count_down(total_micro_second);
    } else {
      uni.showToast({
        title: "发送错误",
        icon: "error"
      })
    }
  }

}


/**
 * 倒计时 验证码
 * @param {*} total_micro_second
 * @returns
 */
 function count_down(total_micro_second) { //发送验证码按钮
    if (total_micro_second <= 0) {
        login_VerifyCode.value = "重新发送"
        // timeout则跳出递归
        return false;
    } else {
        // 渲染倒计时时钟
        login_VerifyCode.value = total_micro_second + "s"
        total_micro_second--;
        if (login_timer.value == true) {
            timer = setTimeout(function () {
                count_down(total_micro_second);
            }, 1000)
        } else {
            login_VerifyCode.value = "获取验证码"
        }
    }
}

function checkPhone(val) {
  if (!/^1((34[0-8])|(8\d{2})|(([35][0-35-9]|4[579]|66|7[35678]|9[1389])\d{1}))\d{7}$/.test(val)) {
    return {flag:false, msg:"请输入正确的手机号"}
  } else {
    return {flag: true, msg: "手机号正确"}
  }
}

function checkPassword(val){
  var pwdRegex = new RegExp('(?=.*[0-9])(?=.*[a-zA-Z]).{8,30}');
  if(!pwdRegex.test(val)){
    return {flag: false, msg: '您的密码复杂度太低(密码中必须包含字母、数字),请及时修改密码!'}
  } else {
    return {flag: true, msg: "密码格式正确"}
  }
}

function checkInputCode(val){
  var checkRegex = new RegExp('[0-9]{6}');
  if(!checkRegex.test(val)){
    return {flag: false, msg: '验证码错误'}
  } else {
    return {flag: true, msg: "验证码格式正确"}
  }
}

function submit() {
  console.log("phone:", phone.value, "password:", password.value, "checkcode:", checkcode.value)
  // 检测输入-手机号
  var {flag, msg} = checkPhone(phone.value)
  if(!flag){
    uni.showToast({
      title: msg,
      icon: "error"
    })
    return false
  }
  // 检测输入-密码
  var {flag, msg} = checkPassword(password.value)
  if(!flag){
    uni.showToast({
      title: msg,
      icon: "error"
    })
    return false
  }
  // 检测输入-验证码
  var {flag, msg} = checkInputCode(checkcode.value)
  if(!flag){
    uni.showToast({
      title: msg,
      icon: "error"
    })
    return false
  }
  // 提交给后台 todo

  console.log("submit success")
  uni.navigateTo({
    url:"/pages/register/register"
  })

}



</script>

<style lang="scss" scoped>
  .content {
    min-height: 100vh;
  }

  .topBox {
    position: relative;
    height: 400rpx;
    background-color: #00aaff;
  }

  .tit {
    width: 90%;
    font-size: 60rpx;
    color: #ffffff;
    position: absolute;
    bottom: 40%;
    left: 50%;
    transform: translateX(-50%);
    font-weight: 600;
  }

  .desc {
    width: 90%;
    font-size: 30rpx;
    color: #f8f8f8;
    position: absolute;
    bottom: 25%;
    left: 50%;
    transform: translateX(-50%);
    display: flex;
    navigator {
      font-weight: 800;
    }
  }

  .bottomBox {
    margin-top: 20rpx;
    min-height: 500rpx;
    padding: 50rpx;
  }

  .item {
    margin-bottom: 60rpx;
    border-bottom: 1px solid #ccc;
  }

  .item .label {
    font-size: 32rpx;
    color: #00aaff;
    font-weight: 600;
    margin-bottom: 20rpx;
  }

  .item input {
    height: 70rpx;
    padding-bottom: 20rpx;
    font-size: 32rpx;
    color: #333;
  }

  .uni-input-placeholder {
    color: #bebebe;
  }

  .yzmBox {
    display: flex;
    justify-content: space-between;
    align-items: center;
  }

  .yzm {
    color: #ffffff;
    font-size: 28rpx;
    padding: 5rpx 8rpx;
    background-color: #00aaff;
  }

  button {
    line-height: 85rpx;
    text-align: center;
    background: rgb(0, 170, 255);
    color: #fff;
    margin-top: 100rpx;
  }

  .agree {
    position: fixed;
    bottom: 60rpx;
    left: 0;
    text-align: center;
    width: 100%;
    color: #919191;
    font-size: 30rpx;
    .protocol{
      color: #00aaff;
    }
  }

</style>

      

修改密码

<template>
  <view class="content">
    <view class="topBox">
      <view class="tit">
        重置密码
      </view>
    </view>

    <view class="bottomBox">
      <view class="item">
        <view class="label">
          账号
        </view>
        <input type="text" v-model="phone" placeholder="请输入您的手机号码" />
      </view>
      <view class="item">
        <view class="label">
          新密码
        </view>
        <view class="uni-input-wrapper">
                    <input class="uni-input" placeholder="请输入新密码" :password="showPassword" />
          <uni-icons :type="showPassword?'smallcircle-filled':'smallcircle'" size="30" @click="changePassword"></uni-icons>
                </view>
      </view>
      <view class="item">
        <view class="label">
          验证码
        </view>
        <view class="yzmBox">
          <input type="text" v-model="checkcode" placeholder="请输入验证码" />
          <view class="yzm" @click="send">
            {{ login_VerifyCode }}
          </view>
        </view>
      </view>
      <button type="default" @click="submit">确定</button>
    </view>
  </view>
</template>

<script setup>
import { ref } from 'vue';
import { BASE_URL } from '../../config';

const phone = ref();
const password = ref();
const checkcode = ref();
const login_VerifyCode = ref("获取验证码"); //发送验证码按钮显示文字
const login_timer = ref(false); //验证码计时器
const timer = ref();        // 计时器
const showPassword = ref(true);   // 密码是否显示

/**切换是否显示密码 */
function changePassword() {
  showPassword.value = !showPassword.value;
}

function send() {
  // 检测输入-手机号
  var {flag, msg} = checkPhone(phone.value)
  if(!flag){
    uni.showToast({
      title: msg,
      icon: "error"
    })
    return false
  }
  if(login_VerifyCode.value == '获取验证码' || login_VerifyCode.value == '重新发送'){
    // 发送验证码给后台
    console.log("start send check code.")
    uni.request({
      url:BASE_URL+'/admin/change/ck',
      data:{phone: phone.value},
      success:(success)=>{
        console.log("ck-res:", success.data)
        if(success.data.code == 1){
          uni.showToast({
            title: "发送成功"
          })
        } else {
          uni.showToast({
            title: success.data.message,
            icon: "error"
          })
        }

      },
      fail:(fail)=>{
        uni.showToast({
          title: "发送错误",
          icon: "error"
        })
      },
      complete:(complete)=>{
        console.log("complete:", complete)
        login_timer.value = true
        var total_micro_second = 60;
        // 验证码倒计时
        count_down(total_micro_second);
      },
    })
  }

}


/**
 * 倒计时 验证码
 * @param {*} total_micro_second
 * @returns
 */
 function count_down(total_micro_second) { //发送验证码按钮
    if (total_micro_second <= 0) {
        login_VerifyCode.value = "重新发送"
        // timeout则跳出递归
        return false;
    } else {
        // 渲染倒计时时钟
        login_VerifyCode.value = total_micro_second + "s"
        total_micro_second--;
        if (login_timer.value == true) {
            timer = setTimeout(function () {
                count_down(total_micro_second);
            }, 1000)
        } else {
            login_VerifyCode.value = "获取验证码"
        }
    }
}

function checkPhone(val) {
  if (!/^1((34[0-8])|(8\d{2})|(([35][0-35-9]|4[579]|66|7[35678]|9[1389])\d{1}))\d{7}$/.test(val)) {
    return {flag:false, msg:"请输入正确的手机号"}
  } else {
    return {flag: true, msg: "手机号正确"}
  }
}

function checkPassword(val){
  var pwdRegex = new RegExp('(?=.*[0-9])(?=.*[a-zA-Z]).{8,30}');
  if(!pwdRegex.test(val)){
    return {flag: false, msg: '您的密码复杂度太低(密码中必须包含字母、数字),请及时修改密码!'}
  } else {
    return {flag: true, msg: "密码格式正确"}
  }
}

function checkInputCode(val){
  var checkRegex = new RegExp('[0-9]{6}');
  if(!checkRegex.test(val)){
    return {flag: false, msg: '验证码错误'}
  } else {
    return {flag: true, msg: "验证码格式正确"}
  }
}

function submit() {
  console.log("phone:", phone.value, "password:", password.value, "checkcode:", checkcode.value)
  // 检测输入-手机号
  var {flag, msg} = checkPhone(phone.value)
  if(!flag){
    uni.showToast({
      title: msg,
      icon: "error"
    })
    return false
  }
  // 检测输入-密码
  var {flag, msg} = checkPassword(password.value)
  if(!flag){
    uni.showToast({
      title: msg,
      icon: "error"
    })
    return false
  }
  // 检测输入-验证码
  var {flag, msg} = checkInputCode(checkcode.value)
  if(!flag){
    uni.showToast({
      title: msg,
      icon: "error"
    })
    return false
  }
  // 提交给后台
  uni.request({
    url:BASE_URL+'/admin/change/password',
    method:'POST',
    header:{'content-type':'application/x-www-form-urlencoded; charset=UTF-8'},
    data:{phone:phone.value, password: password.value, check_code: checkcode.value},
    success:(success)=>{
      console.log("res-register:", success.data)
      if(success.data.code == 1){
        uni.showToast({
          title: '密码修改成功',
          icon: 'success'
        })
        uni.switchTab({
          url:"/pages/login/login"
        })
      } else {
        uni.showToast({
          title: '密码修改失败',
          icon: 'error'
        })
      }
    },
  })

  console.log("submit success")
}



</script>

<style lang="scss" scoped>
  .content {
    min-height: 100vh;
  }

  .topBox {
    position: relative;
    height: 400rpx;
    background-color: #00aaff;
  }

  .tit {
    width: 90%;
    font-size: 60rpx;
    color: #ffffff;
    position: absolute;
    bottom: 40%;
    left: 50%;
    transform: translateX(-50%);
    font-weight: 600;
  }

  .desc {
    width: 90%;
    font-size: 30rpx;
    color: #f8f8f8;
    position: absolute;
    bottom: 25%;
    left: 50%;
    transform: translateX(-50%);
    display: flex;
    navigator {
      font-weight: 800;
    }
  }

  .bottomBox {
    margin-top: 20rpx;
    min-height: 500rpx;
    padding: 50rpx;
  }

  .item {
    margin-bottom: 60rpx;
    border-bottom: 1px solid #ccc;
  }

  .item .label {
    font-size: 32rpx;
    color: #00aaff;
    font-weight: 600;
    margin-bottom: 20rpx;
  }

  .item input {
    height: 70rpx;
    padding-bottom: 20rpx;
    font-size: 32rpx;
    color: #333;
  }

  .uni-input-wrapper{
    display: flex;
    align-items: center;
    justify-content: space-between;
  }

  .uni-input-placeholder {
    color: #bebebe;
  }

  .yzmBox {
    display: flex;
    justify-content: space-between;
    align-items: center;
  }

  .yzm {
    width: 30%;
    text-align: center;
    color: #ffffff;
    font-size: 28rpx;
    padding: 5rpx 8rpx;
    background-color: #00aaff;
  }

  button {
    line-height: 85rpx;
    text-align: center;
    background: rgb(0, 170, 255);
    color: #fff;
    margin-top: 100rpx;
  }

  .agree {
    position: fixed;
    bottom: 60rpx;
    left: 0;
    text-align: center;
    width: 100%;
    color: #919191;
    font-size: 30rpx;
    .protocol{
      color: #00aaff;
    }
  }

</style>

      

 


Comments(0) Add Your Comment

Not Comment!