验证码用户手动输入期间延长倒计时,防止用户输入一半之前60秒结束终止了输验证码步骤

This commit is contained in:
xuxin
2026-06-05 09:54:27 +08:00
parent 403e5e9fc9
commit 8d6282c3e6
+31 -18
View File
@@ -116,10 +116,6 @@
<span class="login-view__spinner"></span> <span class="login-view__spinner"></span>
<span>登录中</span> <span>登录中</span>
</template> </template>
<!-- 即将返回提示 -->
<template v-else-if="isReturning">
即将返回发送验证码
</template>
<!-- 倒计时状态 --> <!-- 倒计时状态 -->
<template v-else> <template v-else>
{{ countdown }} 秒后可继续发送 {{ countdown }} 秒后可继续发送
@@ -174,10 +170,14 @@ const countdown = ref(0)
let countdownTimer: ReturnType<typeof setInterval> | null = null let countdownTimer: ReturnType<typeof setInterval> | null = null
/** 是否正在调用登录接口 */ /** 是否正在调用登录接口 */
const isLoggingIn = ref(false) const isLoggingIn = ref(false)
/** 是否处于"即将返回"提示阶段 */
const isReturning = ref(false)
/** 用户最后一次输入验证码的时间戳 */ /** 用户最后一次输入验证码的时间戳 */
let lastOtpInputTime = 0 let lastOtpInputTime = 0
/** 倒计时结束后等待用户输入冷却的定时器 */
let returnWaitTimer: ReturnType<typeof setTimeout> | null = null
/** 延长倒计时的定时器(每秒递减) */
let extendTimer: ReturnType<typeof setInterval> | null = null
/** 标记60秒倒计时已结束,等待返回中 */
let countdownFinished = false
/** OTP 输入框引用 */ /** OTP 输入框引用 */
const otpInputRef = ref<HTMLInputElement | null>(null) const otpInputRef = ref<HTMLInputElement | null>(null)
@@ -215,21 +215,27 @@ function startCountdown() {
/** 倒计时结束后的返回逻辑 — 考虑用户最近操作 */ /** 倒计时结束后的返回逻辑 — 考虑用户最近操作 */
function triggerReturn() { function triggerReturn() {
// 计算距离用户最后一次输入过了多久 countdownFinished = true
const elapsed = Date.now() - lastOtpInputTime scheduleReturn()
// 如果用户5秒内还在输入,则等待剩余时间后再提示 }
const waitTime = Math.max(0, 5000 - elapsed)
// 先等用户操作冷却 /** 安排返回:用户停止输入5秒后回步骤一,每次输入都重置5秒 */
setTimeout(() => { function scheduleReturn() {
// 显示"即将返回发送验证码"提示5秒 // 清除之前所有定时器,重新开始5秒倒计时
isReturning.value = true if (returnWaitTimer) { clearTimeout(returnWaitTimer); returnWaitTimer = null }
setTimeout(() => { if (extendTimer) { clearInterval(extendTimer); extendTimer = null }
isReturning.value = false
// 直接重置为5秒倒计时
countdown.value = 5
extendTimer = setInterval(() => {
countdown.value--
if (countdown.value <= 0) {
if (extendTimer) { clearInterval(extendTimer); extendTimer = null }
countdownFinished = false
step.value = 1 step.value = 1
otpValue.value = '' otpValue.value = ''
}, 5000) }
}, waitTime) }, 1000)
} }
/** 步骤一:发送验证码 */ /** 步骤一:发送验证码 */
@@ -272,8 +278,15 @@ function handleOtpInput() {
otpValue.value = otpValue.value.replace(/\D/g, '').slice(0, 6) otpValue.value = otpValue.value.replace(/\D/g, '').slice(0, 6)
// 记录用户最后输入时间 // 记录用户最后输入时间
lastOtpInputTime = Date.now() lastOtpInputTime = Date.now()
// 如果倒计时已结束且用户还在输入(未满6位),重新安排返回计时
if (countdownFinished && otpValue.value.length < 6) {
scheduleReturn()
}
// 满6位自动触发登录 // 满6位自动触发登录
if (otpValue.value.length === 6) { if (otpValue.value.length === 6) {
// 取消返回流程
if (returnWaitTimer) { clearTimeout(returnWaitTimer); returnWaitTimer = null }
if (extendTimer) { clearInterval(extendTimer); extendTimer = null }
handleLogin() handleLogin()
} }
} }