import { ref, computed, onUnmounted } from "vue";
import { isValidPhoneNumber } from "@/utils";
interface SendCodeConfig {
fail?: (msg: string) => void; // 手机号验证失败
request: (mobile: string) => Promise<void>; // 请求回调
countDownCount?: number; // 倒计时 默认60秒
}
const useSendCode = (config: SendCodeConfig) => {
// 是否已经触发过
const isTriggered = ref(false);
// 合计时数
const countDown = ref(0);
// 定时器
let timer: NodeJS.Timeout;
// 是否禁用
const disabled = computed(() => countDown.value > 0);
// 发送按钮的文案
const sendBtnText = computed(() => {
if (disabled.value) return `${countDown.value}s`;
if (isTriggered.value) return "再次发送";
return "发送验证码";
});
const send = async (mobile: string): Promise<void> => {
if (disabled.value) return;
if (!isValidPhoneNumber(mobile)) {
console.error("手机号格式错误");
config.fail && config.fail("手机号格式错误");
return;
}
await config.request(mobile);
isTriggered.value = true;
countDown.value = config.countDownCount || 60;
if (timer) clearInterval(timer);
timer = setInterval(() => {
countDown.value--;
if (countDown.value === 0) clearInterval(timer);
}, 1000);
};
onUnmounted(() => {
clearInterval(timer);
});
return { countDown, send, disabled, sendBtnText };
};
export default useSendCode;
isValidPhoneNumber.js
export function isValidPhoneNumber(str: string): boolean {
// 检查字符串长度是否为 11 位
if (str.length !== 11) {
return false;
}
// 检查字符串是否以 "1" 开头
if (str.charAt(0) !== "1") {
return false;
}
// 使用正则表达式检查字符串是否仅包含数字
const numericRegex = /^\d+$/;
if (!numericRegex.test(str)) {
return false;
}
return true;
}
发送验证码按钮的使用
<a-button
type="primary"
style="width: 100px; padding: 0"
@click="handleClickSend"
:disabled="disabled"
>
{{ sendBtnText }}
</a-button>
script中使用
/**
* 发送验证码
*/
const { send, disabled, sendBtnText } = useSendCode({
countDownCount: 10,
fail: (msg) => {
// 手机号验证失败
message.error(msg, 0);
},
request: async (mobile) => {
// 请求回调
console.log("请求中", mobile);
const res = await sendRandomCode({ phoneNumber: mobile });
console.log("res", res);
if (!res.success) {
message.error(res.msg);
}
},
});
const handleClickSend = () => send(formState.tel);