看见比较好的代码抄袭

2022-06-23  本文已影响0人  糖醋里脊120625

hooks

import { reactive, toRefs, unref } from 'vue';
import { Toast } from 'vant';
import API_VERIFICATION from '@/apis/verification';
import { sms } from '@/constants/modules/user';
import { isMobile } from '@/utils/validate';

/**
 * 短信验证码
 */
export function useSmsCode() {
  const state = reactive({
    // 短信验证码
    mobile: '',
    smsCode: '',
    smsTimer: null as TimeoutHandle | null,
    smsText: '获取验证码',
    smsCount: sms.count,
    // 图形验证码
    captchaShow: false,
  });

  function onSmsBtnClicked() {
    if (!unref(state.mobile)) {
      Toast('请输入手机号信息');
      return;
    }

    if (!isMobile(unref(state.mobile))) {
      Toast('手机号格式错误');
      return;
    }

    state.captchaShow = true;
  }

  function onSmsSend({ requestId, code }) {
    API_VERIFICATION.verificationSmsGet({
      mobile: unref(state.mobile),
      key: requestId,
      picCode: code,
    }).then(() => {
      Toast({
        message: '短信已发送,请查收',
        duration: 2000,
      });
      countdown(); // 立即执行一次,避免 setInterval 延迟
      state.smsTimer = setInterval(countdown, 1000);
    });
  }

  function countdown() {
    if (state.smsCount > 0) {
      state.smsCount--;
      state.smsText = `已发送(${state.smsCount}s)`;
    } else {
      state.smsCount = sms.count;
      state.smsText = `重新发送`;
      clearInterval(Number(state.smsTimer));
      state.smsTimer = null;
    }
  }

  return {
    ...toRefs(state),
    onSmsBtnClicked,
    onSmsSend,
    countdown,
  };
}

vue文件

<template>
  <div class="container">
    <div class="main">
      <div class="h2">{{ title }}</div>
      <div class="form">
        <div class="form-item">
          <div class="form-item-country">中国 +86</div>
          <van-field
            v-model="mobile"
            class="form-field"
            :border="false"
            type="tel"
            placeholder="请输入手机号"
            clearable
          />
        </div>
        <div class="form-item">
          <van-field v-model="nick" class="form-field" :border="false" type="tel" placeholder="请输入昵称" clearable>
            <template #right-icon>
              <img class="icon-random" :src="randomIcon" alt="" @click="onNickRandom" />
            </template>
          </van-field>
        </div>
        <div class="form-item">
          <van-field
            v-model="smsCode"
            class="form-field"
            :border="false"
            type="number"
            placeholder="请输入4位验证码"
            clearable
          />
          <template v-if="smsTimer">
            <span class="sms-btn countdown">{{ smsText }}</span>
          </template>
          <template v-else>
            <span class="sms-btn" @click="onSmsBtnClicked">{{ smsText }}</span>
          </template>
        </div>
        <div class="form-item">
          <PwdField
            key="pwd"
            v-model="pwd"
            class="form-field"
            :border="false"
            placeholder="请设置8-25位(数字+字母)密码"
            clearable
          />
        </div>
        <div class="form-item">
          <PwdField
            key="pwd2"
            v-model="pwd2"
            class="form-field"
            :border="false"
            placeholder="请再次输入密码"
            clearable
          />
        </div>
        <van-button
          class="form-submit"
          block
          :disabled="!submitted"
          :loading="submitLoading"
          loading-text="注册中..."
          type="primary"
          @click="onSubmit"
          >确定</van-button
        >
      </div>
    </div>
    <div class="footer">
      <div class="footer-agreement">
        <van-checkbox v-model="agree" icon-size="16px" />
        <span> 阅读并同意</span><a href="javascript:void(0);">《用户协议》</a>和<a href="javascript:void(0);"
          >《隐私政策d》</a
        >
      </div>
    </div>
    <!-- 图形验证码 -->
    <Captcha v-model:show="captchaShow" @success="onSmsSend" />
  </div>
</template>




<script lang="ts" setup>
import { computed, onMounted, ref, unref } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { Toast } from 'vant';
import Captcha from '@/components/Captcha/index.vue';
import PwdField from '@/components/PwdField/index.vue';
import { nickList } from '@/constants/modules/user';
import { isMobile, isPassWord, isSame } from '@/utils/validate';
import { randomIntegerInRange } from '@/utils/lodash';
import randomIcon from '@/assets/icons/shaizi.svg';

import { useUserStore } from '@/store/modules/user';
import { useSmsCode } from '@/hooks/shared/useSmsCode';

const userStore = useUserStore();

onMounted(() => {
  onNickRandom();
});

const router = useRouter();
const route = useRoute();

const title = ref('免费注册');
const { mobile, smsCode, smsTimer, smsText, captchaShow, onSmsBtnClicked, onSmsSend } = useSmsCode();
const pwd = ref('');
const pwd2 = ref('');

const nick = ref('');
function onNickRandom() {
  nick.value = nickList[randomIntegerInRange(0, nickList.length - 1)];
}

const agree = ref(true);

const submitLoading = ref(false);
const submitted = computed(() => {
  return unref(mobile) && unref(nick) && unref(smsCode) && unref(pwd) && unref(pwd2);
});

function onSubmit() {
  if (!isMobile(unref(mobile))) {
    Toast('手机号格式错误');
    return;
  }

  if (!isPassWord(unref(pwd))) {
    Toast('请设置8-25位(数字+字母)密码');
    return;
  }

  if (!isSame(unref(pwd), unref(pwd2))) {
    Toast('2次输入密码不一致');
    return;
  }

  const params = {
    mobile: unref(mobile),
    code: unref(smsCode),
    nick: unref(nick),
    pwd: unref(pwd),
    autoLogin: true,
  };

  submitLoading.value = true;

  userStore
    .login({ provider: 'register', params })
    .then(() => {
      submitLoading.value = false;
      route.query.redirect ? router.replace({ path: route.query.redirect as string }) : router.replace({ path: '/' });
      Toast.success('注册成功');
    })
    .catch((error) => {
      submitLoading.value = false;
      console.error(error);
    });
}
</script>



<style lang="less" scoped>

</style>

上一篇下一篇

猜你喜欢

热点阅读