vue3使用setup语法糖配合TS和Element-Plus实现手机验证码登录

首先,通过getCode方法调用api接口,在调用接口前,需要对表单中的电话号码进行校验,可以使用element-plus的validateField方法对表单的单一字段进行校验。调用api接口成功获取验证码之后,调用倒计时方法。获取失败则对错误进行处理。

通过调用倒计时方法修改获取验证码的按钮状态,防止用户多次点击。

获取验证码成功之后调用登录方法,进行登录接口,登录成功跳转至首页

全部代码如下:

<template>
  <div class="form">
    <div class="code">
      <div class="image-wrapper_15 flex-row">
        <img
          class="label_14"
          referrerpolicy="no-referrer"
          src="https://lanhu.oss-cn-beijing.aliyuncs.com/c4fe81a8aa2ee4dda5afd4861e3a168c"
        />
        <img
          class="image_26"
          referrerpolicy="no-referrer"
          src="https://lanhu.oss-cn-beijing.aliyuncs.com/8307344052962e63f1e639924c80db38"
        />
      </div>
      <div class="hidden_image"></div>
    </div>
    <div class="form">
      <p class="form-title">登录</p>
      <el-form ref="formRef" :model="form" :rules="rules" size="small">
        <el-form-item prop="user_phone">
          <el-input v-model="form.user_phone" class="w-50 m-2" placeholder="请输入手机号" size="large">
            <template #append>
              <el-button
                size="large"
                style="width: 150px; color: white; background-color: #409eff"
                @click="getCode(formRef)"
                :loading="code_loading"
                :disabled="code_disabled"
              >
                {{ code_text }}
              </el-button>
            </template>
          </el-input>
        </el-form-item>
        <el-form-item prop="code">
          <el-input v-model="form.code" class="w-50 m-2" placeholder="请输入验证码" size="large" />
        </el-form-item>
      </el-form>
      <div class="check-btn">
        <el-checkbox size="large" :checked="accept" @change="isAccept">
          我已阅读并接受
          <el-button link size="large" style="margin-bottom: 2px; color: #409eff">服务条款</el-button>
        </el-checkbox>
      </div>
      <el-button style="color: white; background-color: #409eff; border-radius: 20px" size="large" @click="onSubmit(formRef)">
        登录/注册
      </el-button>
      <!-- <el-button link size="large" @click="register('register')" style="margin-top: 20px; color: #409eff">立即注册</el-button> -->
    </div>
  </div>
</template>

<script lang="ts" setup>
import { ElMessage, ElNotification, FormInstance } from "element-plus";
import { onBeforeUnmount, onMounted, ref } from "vue";
import { useRouter } from "vue-router";
import { useUserStore } from "@/stores/modules/user";
import { getTimeState } from "@/utils/index";
import { initDynamicRouter } from "@/routers/modules/dynamicRouter";
import { HOME_URL } from "@/config";
import { checkPhoneNumber } from "@/utils/eleValidate";
import { CodeApi, phoneLoginApi } from "@/api/modules/login";
const accept = ref<boolean>(false);
const userStore = useUserStore();
const formRef = ref<FormInstance>();
const router = useRouter();
const loading = ref(false);
const code_text = ref("获取验证码");
const code_disabled = ref(false);
const code_loading = ref(false);
const code_timer = ref<number | null | undefined>();
const form = ref({
  //表单信息
  user_phone: "",
  code: ""
});
const getCode = (formRef: FormInstance | undefined) => {
  if (!formRef) {
    return;
  }
  formRef.validateField("user_phone", (valid: any) => {
    if (valid) {
      code_loading.value = true;
      code_text.value = "发送中";
      CodeApi({ mobile: form.value.user_phone })
        .then(res => {
          if (res.code === 200) {
            ElMessage.success("获取成功");
            countdown();
          }
        })
        .catch(() => {
          code_loading.value = false;
          code_text.value = "获取验证码";
        });
    }
  });
};
const validateVcode = (rule: any, value: any, callback: any) => {
  //自定义验证
  if (value === "") {
    callback(new Error("验证码不能为空"));
  } else {
    callback();
  }
};
//表单验证
const rules = ref({
  user_phone: [{ validator: checkPhoneNumber, trigger: "change" }],
  code: [{ validator: validateVcode, trigger: "change" }]
});
const onSubmit = (formRef: FormInstance | undefined) => {
  if (!formRef) {
    return;
  }
  formRef.validate((valid: any) => {
    //执行规则验证
    if (valid) {
      //通过时执行
      if (!accept.value) {
        ElMessage.error("请选择接受服务条款");
        return;
      }
      login();
    } else {
      return false;
    }
  });
};
const login = async () => {
  loading.value = true;
  try {
    // 1.执行登录接口
    await phoneLoginApi({ mobile: form.value.user_phone, code: form.value.code }).then(res => {
      userStore.setToken(res.data.token);
    });
    // 2.添加动态路由
    await initDynamicRouter();

    // // 3.清空 tabs、keepAlive 数据
    // tabsStore.closeMultipleTab();
    // keepAliveStore.setKeepAliveName();

    // 4.跳转到首页
    router.push(HOME_URL);
    ElNotification({
      title: getTimeState(),
      message: "欢迎登录-灵工谷",
      type: "success",
      duration: 3000
    });
  } finally {
    loading.value = false;
  }
};
const isAccept = () => {
  accept.value = !accept.value;
};
onMounted(() => {
  // 监听 enter 事件(调用登录)
  document.onkeydown = (e: KeyboardEvent) => {
    e = (window.event as KeyboardEvent) || e;
    if (e.code === "Enter" || e.code === "enter" || e.code === "NumpadEnter") {
      if (loading.value) return;
      onSubmit(formRef.value);
    }
  };
});
/** 倒计时 */
const countdown = () => {
  let second = 60; // 默认时间
  code_loading.value = false; // 取消加载
  code_disabled.value = true; // 禁用按钮
  code_text.value = `${second}秒`; // 按钮文本
  // 判断是否存在定时器,存在则先清除
  if (code_timer.value) {
    clearInterval(code_timer.value);
  }
  // 开启定时器
  code_timer.value = Number(
    setInterval(() => {
      second--;
      code_text.value = `${second}秒`; // 按钮文本
      if (second <= 0) {
        code_text.value = `重新获取`; // 按钮文本
        code_disabled.value = false; // 启用按钮
        clearInterval(code_timer.value as number); // 清除倒计时
      }
    }, 1000)
  );
};

// 组件销毁之前 - 生命周期
onBeforeUnmount(() => {
  clearInterval(code_timer.value as number); // 清除倒计时
});
</script>

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值