CodeFormItem.vue 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. <template>
  2. <div class="verification-code-input">
  3. <el-form-item prop="code" :rules="[
  4. { required: true, message: '请输入验证码'}
  5. ]">
  6. <!-- 输入框 -->
  7. <el-input @keydown.enter="debouncedSendAuthCode" class="bf-login-form-code" oninput="this.value = this.value.replace(/[^0-9]/g, '')" minlength="6"
  8. maxlength="6" v-model.number="code" clearable
  9. placeholder="请输入验证码"/>
  10. <!-- 获取验证码按钮 -->
  11. <el-button @click="debouncedSendAuthCode" class="bf-login-form-code-btn" type="primary"
  12. :disabled="countdownActive">
  13. {{ countdownActive ? `${remainingTime} 秒后重新获取` : '获取验证码' }}
  14. </el-button>
  15. </el-form-item>
  16. </div>
  17. </template>
  18. <script setup lang="ts">
  19. import {ref, onBeforeUnmount} from 'vue';
  20. import {debounce} from "@/utils/common.ts";
  21. // 使用 defineEmits 声明组件可以发射的事件
  22. const emits = defineEmits(['sendAuthCode']);
  23. // 组件内部的状态
  24. const code = defineModel('code');
  25. const countdown = ref<NodeJS.Timeout | null>(null);
  26. const countdownDuration = 60;
  27. const remainingTime = ref(countdownDuration);
  28. const countdownActive = ref(false);
  29. // 防抖处理获取验证码的函数
  30. const debouncedSendAuthCode = debounce(sendAuthCode, 500);
  31. // 发送验证码的函数
  32. function sendAuthCode() {
  33. // 如果正在倒计时,直接返回,防止连续点击
  34. if (countdownActive.value) return;
  35. // 通过发射事件通知父组件,同时传递启动倒计时的回调函数
  36. emits('sendAuthCode', startCountdown);
  37. }
  38. // 启动倒计时的函数
  39. function startCountdown() {
  40. countdownActive.value = true;
  41. // 设置间隔为1秒的定时器,更新剩余时间
  42. countdown.value = setInterval(() => {
  43. remainingTime.value--;
  44. // 当剩余时间为0时清除定时器,重置状态
  45. if (remainingTime.value <= 0) {
  46. clearInterval(countdown.value!);
  47. countdownActive.value = false;
  48. remainingTime.value = countdownDuration;
  49. }
  50. }, 1000);
  51. }
  52. // 在组件销毁前清除倒计时器
  53. onBeforeUnmount(() => {
  54. clearInterval(countdown.value!);
  55. });
  56. </script>
  57. <style scoped lang="scss">
  58. :deep(.el-form-item__content) {
  59. flex-wrap: unset;
  60. }
  61. </style>