123 lines
3.0 KiB
Vue
123 lines
3.0 KiB
Vue
<template>
|
||
<!-- 验证码按钮 - 纯功能高度定制版 -->
|
||
<el-button :type="buttonType" :size="buttonSize" :disabled="disabled || isCountingDown" :loading="isLoading"
|
||
class="captcha-btn" @click="handleGetCaptcha">
|
||
<!-- 倒计时状态展示 -->
|
||
<span v-if="isCountingDown">{{ countDown }} 秒后重新获取</span>
|
||
<!-- 正常状态展示 -->
|
||
<span v-else>{{ buttonText }}</span>
|
||
</el-button>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { ref } from 'vue'
|
||
import { getSms } from "@/api/common";
|
||
|
||
// 接收父组件传递的自定义参数
|
||
const props = defineProps({
|
||
// 验证码类型
|
||
// editShopInfoOpePwd 店铺操作密码
|
||
// wxMiniPwd 微信小程序用户登录密码
|
||
// shopPwd 店铺登录密码
|
||
type: {
|
||
type: String,
|
||
default: 'editShopInfoOpePwd'
|
||
},
|
||
// 按钮类型(primary/success/warning/danger/info/default)
|
||
buttonType: {
|
||
type: String,
|
||
default: 'primary'
|
||
},
|
||
// 按钮尺寸(large/default/small)
|
||
buttonSize: {
|
||
type: String,
|
||
default: 'default'
|
||
},
|
||
// 正常状态按钮文字
|
||
buttonText: {
|
||
type: String,
|
||
default: '获取验证码'
|
||
},
|
||
// 倒计时总秒数
|
||
countDownNum: {
|
||
type: Number,
|
||
default: 60
|
||
},
|
||
// 手动控制按钮禁用状态
|
||
disabled: {
|
||
type: Boolean,
|
||
default: false
|
||
}
|
||
})
|
||
|
||
// 发射事件给父组件
|
||
const emit = defineEmits(['get-captcha'])
|
||
|
||
// 加载状态(请求验证码时)
|
||
const isLoading = ref(false)
|
||
// 是否正在倒计时
|
||
const isCountingDown = ref(false)
|
||
// 倒计时秒数
|
||
const countDown = ref(0)
|
||
// 倒计时定时器
|
||
let timer = null
|
||
|
||
// 获取验证码点击事件
|
||
const handleGetCaptcha = async () => {
|
||
// 倒计时中 / 加载中 / 禁用状态 禁止点击
|
||
if (isCountingDown.value || isLoading.value || props.disabled) return
|
||
|
||
try {
|
||
// 开启加载状态
|
||
isLoading.value = true
|
||
// 触发父组件的请求方法(真正的接口请求写在父组件)
|
||
await getSms({ type: props.type });
|
||
ElNotification.success({
|
||
title: '成功',
|
||
message: '验证码已发送,请注意查收',
|
||
});
|
||
// ======================
|
||
// 请求成功 → 开始倒计时
|
||
// ======================
|
||
startCountDown()
|
||
} catch (error) {
|
||
// 请求失败 → 不触发倒计时,控制台提示
|
||
console.error('', error)
|
||
} finally {
|
||
// 关闭加载状态
|
||
setTimeout(() => {
|
||
isLoading.value = false
|
||
}, 500) // 适当延迟,避免闪烁
|
||
}
|
||
}
|
||
|
||
// 倒计时核心逻辑
|
||
const startCountDown = () => {
|
||
// 初始化倒计时时间
|
||
countDown.value = props.countDownNum
|
||
isCountingDown.value = true
|
||
|
||
// 开启定时器
|
||
timer = setInterval(() => {
|
||
countDown.value--
|
||
// 倒计时结束
|
||
if (countDown.value <= 0) {
|
||
clearInterval(timer)
|
||
timer = null
|
||
isCountingDown.value = false
|
||
}
|
||
}, 1000)
|
||
}
|
||
|
||
// 页面销毁时清除定时器(防止内存泄漏)
|
||
onUnmounted(() => {
|
||
if (timer) clearInterval(timer)
|
||
})
|
||
</script>
|
||
|
||
<style scoped>
|
||
/* 你可以在这里自定义按钮默认样式,也可以在父组件覆盖 */
|
||
.captcha-btn {
|
||
min-width: 120px;
|
||
}
|
||
</style> |