phone-form.vue 2.88 KB
<template>
  <a-form ref="fromRef" :model="userInfo" :rules="rules" class="login-form" layout="vertical">
    <a-form-item field="phone" hide-label>
      <a-select
        v-model="userInfo.area"
        style="flex: 100px; margin-right: 15px"
        :options="areaOption"
        :virtual-list-props="{ height: 200 }"
      />
      <a-input v-model="userInfo.phone" placeholder="请输入登陆手机号" :max-length="11">
        <template #prefix>
          <icon-phone />
        </template>
      </a-input>
    </a-form-item>
    <a-form-item show-colon hide-label>
      <a-input v-model="userInfo.code" hide-button :max-length="6" placeholder="验证码" @input="formatCode">
        <template #prefix>
          <icon-message />
        </template>
        <template #suffix>
          <a-link type="text" class="login-form-sms-btn" :disabled="countTime !== 0" @click="onSend()">
            {{ countTime <= 0 ? '获取验证码' : countTime + 's' }}
          </a-link>
        </template>
      </a-input>
    </a-form-item>
  </a-form>
</template>

<script lang="ts" setup>
import { IconMessage, IconPhone } from '@arco-design/web-vue/es/icon';
import { onMounted, ref } from 'vue';
import { useIntervalFn } from '@vueuse/core';
import { FormInstance } from '@arco-design/web-vue/es/form';
import { AttributeData } from '@/types/global';
import { Message } from '@arco-design/web-vue';
import useProviderApi from '@/api/provider';
import { map, union } from 'lodash';

const fromRef = ref<FormInstance>();
const countTime = ref(0);

const userInfo = ref({ area: '+86', phone: '', code: '' });
const areaOption = ref<string[]>([]);

onMounted(() => {
  // eslint-disable-next-line no-return-assign
  useProviderApi.area().then(({ data }) => (areaOption.value = union(map(data, (item) => item.identifier))));
});

const rules = {
  phone: [{ required: true, message: '请输入手机号' }],
  code: [{ required: true, message: '请输入验证码' }],
};

// eslint-disable-next-line no-return-assign
const { pause, resume } = useIntervalFn(() => (countTime.value <= 0 ? pause() : (countTime.value -= 1)), 1000);

const onSend = async () => {
  if (countTime.value !== 0 || (await fromRef.value?.validateField('phone'))) {
    return;
  }
  useProviderApi.sms('login', userInfo.value.phone, userInfo.value.area).then(() => {
    Message.success('短信发送成功,请注意查收!');
    countTime.value = 60;
    resume();
  });
};

const onSubmit = (callback: (value: AttributeData) => void) => {
  fromRef.value?.validate((errors) => !errors && callback(userInfo.value));
};

const formatCode = (value: string) => {
  userInfo.value.code = value.replace(/\D/g, '').slice(0, 6);
};

defineExpose({ onSubmit });
</script>

<style lang="less" scoped>
.login-form {
  &-error-msg {
    height: 32px;
    color: rgb(var(--red-6));
    line-height: 32px;
  }

  &-sms-btn {
    padding-left: -12px;
    font-size: 12px;
  }
}
</style>