feat: 重置密码倒计时机制修改

This commit is contained in:
zhangyahui
2025-10-31 14:54:42 +08:00
parent 8353e81a0f
commit d98bedd663
2 changed files with 105 additions and 19 deletions

View File

@@ -22,7 +22,6 @@
v-else-if="step === 'verify'"
:ct="emailCode"
@nextStep="handleCheckVerifyCode"
@resend="handleSendVerifyCode"
/>
<Password v-else-if="step === 'password'" @sucess="handleSuccess" />
</div>
@@ -42,7 +41,7 @@ import Mail from './components/Mail.vue'
import Verify from './components/Verify.vue'
import Password from './components/Password.vue'
import { showToast } from 'vant'
import { precheckEmail, resetPassword } from '@/api/login'
import { resetPassword } from '@/api/login'
import { encryptPassword } from '@/utils/tools'
const router = useRouter()
@@ -80,10 +79,8 @@ const handleSendVerifyCode = (data: any) => {
if (data?.email) {
fromData.value.email = data?.email
}
precheckEmail({ email: fromData.value.email }).then(() => {
showToast('the verification code has been sent to your email')
handleStep('verify')
})
// 只切换步骤,验证码的发送由 Verify 组件负责
handleStep('verify')
}
const handleCheckVerifyCode = (data: any) => {

View File

@@ -31,8 +31,10 @@
<div class="btn" @click="handleConfirmCaptcha">Confirm</div>
</template>
<script setup lang="ts">
import { ref, computed, watch, onMounted, nextTick } from 'vue'
import { ref, computed, watch, onMounted, onUnmounted, nextTick } from 'vue'
import { showToast } from 'vant'
import { getLocal, removeLocal, setLocal } from '@/utils/local'
import { precheckEmail } from '@/api/login'
// Props
const props = defineProps({
@@ -48,7 +50,7 @@ const props = defineProps({
const agreePolicy = ref(false)
// Emits
const emit = defineEmits(['nextStep','resend'])
const emit = defineEmits(['nextStep'])
// Reactive data
const loading = ref(false)
@@ -66,24 +68,88 @@ const cIndex = computed(() => {
// const lastCode = computed(() => getCtData.value[ctSize.value - 1])
const countdown = ref(60)
const handleCountdown = () => {
const timer = setInterval(() => {
const countdownTimer = ref<number | null>(null)
const COUNTDOWN_KEY = 'verify_code_countdown'
const COUNTDOWN_EMAIL_KEY = 'verify_code_email'
const COUNTDOWN_DURATION = 60 // 60秒倒计时
// 清除倒计时数据
const clearCountdownData = () => {
removeLocal(COUNTDOWN_KEY)
removeLocal(COUNTDOWN_EMAIL_KEY)
}
// 保存倒计时开始时间
const saveCountdownStart = () => {
const timestamp = Date.now()
setLocal(String(timestamp), COUNTDOWN_KEY)
setLocal(props.email, COUNTDOWN_EMAIL_KEY)
}
// 从 localStorage 恢复倒计时
const restoreCountdown = () => {
const savedTimestamp = getLocal(COUNTDOWN_KEY)
const savedEmail = getLocal(COUNTDOWN_EMAIL_KEY)
// 检查是否有保存的倒计时,且是同一个邮箱
if (savedTimestamp && savedEmail === props.email) {
const elapsed = Math.floor((Date.now() - Number(savedTimestamp)) / 1000)
const remaining = COUNTDOWN_DURATION - elapsed
if (remaining > 0) {
// 如果还有剩余时间,恢复倒计时
countdown.value = remaining
startCountdown()
return true
} else {
// 如果已经过期,清除数据
clearCountdownData()
}
}
return false
}
// 开始倒计时
const startCountdown = () => {
// 清除之前的定时器
if (countdownTimer.value) {
clearInterval(countdownTimer.value)
}
countdownTimer.value = setInterval(() => {
countdown.value--
if (countdown.value <= 0) {
clearInterval(timer)
if (countdownTimer.value) {
clearInterval(countdownTimer.value)
countdownTimer.value = null
}
clearCountdownData()
}
}, 1000)
}, 1000) as unknown as number
}
const handleSendVerifyCode = () => {
handleCountdown()
// 发送验证码
const handleSendVerifyCode = async () => {
if (loading.value) return
loading.value = true
try {
await precheckEmail({ email: props.email })
showToast('the verification code has been sent to your email')
countdown.value = COUNTDOWN_DURATION
saveCountdownStart()
startCountdown()
} catch (error) {
console.error('发送验证码失败:', error)
showToast('Failed to send verification code, please try again')
} finally {
loading.value = false
}
}
const handleResend = () => {
const handleResend = async () => {
if (countdown.value > 0) return
countdown.value = 60
handleSendVerifyCode()
emit('resend')
await handleSendVerifyCode()
}
const handleConfirmCaptcha = () => {
@@ -97,6 +163,12 @@ const handleConfirmCaptcha = () => {
showToast('please enter the correct verification code.')
return
}
// 验证成功后清除倒计时数据
clearCountdownData()
if (countdownTimer.value) {
clearInterval(countdownTimer.value)
countdownTimer.value = null
}
emit('nextStep', { code: password })
}
@@ -208,7 +280,24 @@ watch(cIndex, () => {
// Lifecycle
onMounted(() => {
resetCaret()
handleSendVerifyCode()
// 尝试恢复倒计时,如果无法恢复则发送验证码
const restored = restoreCountdown()
if (!restored) {
// 如果没有恢复倒计时,说明倒计时已结束或不存在,需要发送验证码
handleSendVerifyCode()
}
// 如果恢复了倒计时,说明倒计时还未结束,不发送验证码
})
onUnmounted(() => {
// 组件卸载时清理定时器
if (countdownTimer.value) {
clearInterval(countdownTimer.value)
countdownTimer.value = null
}
if (timeout.value) {
clearTimeout(timeout.value)
}
})
// Expose methods for parent component