91 lines
2.3 KiB
Vue
91 lines
2.3 KiB
Vue
|
|
<template>
|
|||
|
|
<view class="input-item">
|
|||
|
|
<wd-icon name="lock-on" size="20px" color="#1890ff" />
|
|||
|
|
<wd-input
|
|||
|
|
:model-value="modelValue"
|
|||
|
|
placeholder="请输入验证码"
|
|||
|
|
clearable
|
|||
|
|
clear-trigger="focus"
|
|||
|
|
no-border
|
|||
|
|
type="number"
|
|||
|
|
:maxlength="6"
|
|||
|
|
@update:model-value="$emit('update:modelValue', $event)"
|
|||
|
|
/>
|
|||
|
|
<view
|
|||
|
|
class="whitespace-nowrap border-l-1rpx border-l-[#e5e5e5] border-l-solid px-20rpx text-28rpx text-[#1890ff]"
|
|||
|
|
@click="handleSendCode"
|
|||
|
|
>
|
|||
|
|
<text :class="{ 'text-gray-400': countdown > 0 }">
|
|||
|
|
{{ countdown > 0 ? `${countdown} 秒后重发` : "获取验证码" }}
|
|||
|
|
</text>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
</template>
|
|||
|
|
|
|||
|
|
<script lang="ts" setup>
|
|||
|
|
import { onUnmounted, ref } from "vue";
|
|||
|
|
import { useToast } from "wot-design-uni";
|
|||
|
|
import { sendSmsCode } from "@/api/login";
|
|||
|
|
import { isMobile } from "@/utils/validator";
|
|||
|
|
|
|||
|
|
defineOptions({
|
|||
|
|
name: "CodeInput",
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
const props = defineProps<{
|
|||
|
|
modelValue: string; // 验证码值 (v-model)
|
|||
|
|
mobile: string; // 手机号
|
|||
|
|
scene: number; // 短信场景:21-登录 23-重置密码
|
|||
|
|
beforeSend?: () => boolean; // 发送前的校验函数,返回 false 则不发送
|
|||
|
|
}>();
|
|||
|
|
|
|||
|
|
defineEmits<{
|
|||
|
|
"update:modelValue": [value: string];
|
|||
|
|
}>();
|
|||
|
|
|
|||
|
|
const toast = useToast();
|
|||
|
|
const countdown = ref(0); // 验证码倒计时,单位秒
|
|||
|
|
let countdownTimer: ReturnType<typeof setInterval> | null = null; // 倒计时定时器
|
|||
|
|
|
|||
|
|
/** 页面卸载时清除倒计时定时器 */
|
|||
|
|
onUnmounted(() => {
|
|||
|
|
if (countdownTimer) {
|
|||
|
|
clearInterval(countdownTimer);
|
|||
|
|
countdownTimer = null;
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
/** 发送验证码 */
|
|||
|
|
async function handleSendCode() {
|
|||
|
|
// 执行前置校验
|
|||
|
|
if (props.beforeSend && !props.beforeSend()) {
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
if (countdown.value > 0) {
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
if (!props.mobile) {
|
|||
|
|
toast.warning("请输入手机号");
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
if (!isMobile(props.mobile)) {
|
|||
|
|
toast.warning("请输入正确的手机号");
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 发送验证码
|
|||
|
|
await sendSmsCode({ mobile: props.mobile, scene: props.scene });
|
|||
|
|
toast.success("验证码已发送");
|
|||
|
|
|
|||
|
|
// 开始倒计时
|
|||
|
|
countdown.value = 60;
|
|||
|
|
countdownTimer = setInterval(() => {
|
|||
|
|
countdown.value--;
|
|||
|
|
if (countdown.value <= 0) {
|
|||
|
|
clearInterval(countdownTimer!);
|
|||
|
|
countdownTimer = null;
|
|||
|
|
}
|
|||
|
|
}, 1000);
|
|||
|
|
}
|
|||
|
|
</script>
|