diff --git a/src/js/utils/flowLimite.js b/src/js/utils/flowLimite.js new file mode 100644 index 0000000..78b949e --- /dev/null +++ b/src/js/utils/flowLimite.js @@ -0,0 +1,31 @@ +import { ElMessage } from 'element-plus' + +/** + * 流控:在duration时间内只允许task任务被执行countLimit次 + * @param {*} task 待执行的任务Promise,可以是请求或者其他 + * @param {*} countLimit 控制数量 + * @param {*} duration 控制周期 ms + * @returns + */ +export const flowLimiteWrapper = (task, countLimit, duration) => { + let count = 0 + return async () => { + if (count >= countLimit) { + ElMessage.warning('请求太过频繁,请稍后再试') + return Promise.reject(new Error('REQUEST_LIMITED')) // 返回一个拒绝的 Promise + } + + count++ + setTimeout(() => { + count-- + }, duration) + + // 执行任务并确保返回 Promise + try { + const result = await task() + return Promise.resolve(result) // 原始任务可能是同步或异步的 + } catch (error) { + return Promise.reject(error) // 捕获同步错误并转为 Promise 拒绝 + } + } +} diff --git a/src/views/LoginPage.vue b/src/views/LoginPage.vue index daa8a14..8ae18a1 100644 --- a/src/views/LoginPage.vue +++ b/src/views/LoginPage.vue @@ -11,6 +11,7 @@ import { import { userStore } from '@/stores' import { generateClientId } from '@/js/utils/common' import { ElMessage } from 'element-plus' +import { flowLimiteWrapper } from '@/js/utils/flowLimite' const isRegister = ref(false) @@ -71,10 +72,7 @@ const userData = userStore() const register = async () => { await form.value.validate() // 注册之前预校验 try { - await userVerifyCaptchaService({ - id: captchaId.value, - code: formModel.value.captchaCode - }) + await verifyCaptchaWrapper() } catch (error) { // 触发form表单报错提醒 formModel.value.captchaCode = '' @@ -126,19 +124,42 @@ const captchaId = ref('') const captchaImage = ref('') const switchRegister = () => { - getCaptchaImage() + getCaptchaImageWrapper().catch(() => { + // do nothing + }) isRegister.value = true } -const getCaptchaImage = () => { - captchaId.value = '' - captchaImage.value = '' - userGetCaptchaService().then(async (res) => { - captchaId.value = res.data.data.id - captchaImage.value = res.data.data.base64 +const onClickCaptcha = () => { + getCaptchaImageWrapper().catch(() => { + // do nothing }) } +// 60s内只能被执行10次 +const getCaptchaImageWrapper = flowLimiteWrapper( + async () => { + captchaId.value = '' + captchaImage.value = '' + return userGetCaptchaService().then((res) => { + captchaId.value = res.data.data.id + captchaImage.value = res.data.data.base64 + }) + }, + 10, + 60000 +) +const verifyCaptchaWrapper = flowLimiteWrapper( + async () => { + return userVerifyCaptchaService({ + id: captchaId.value, + code: formModel.value.captchaCode + }) + }, + 10, + 60000 +) + watch(isRegister, () => { formModel.value = { account: !isRegister.value && isRemenberMe.value ? userData.user.account : '', @@ -214,7 +235,7 @@ watch(isRegister, () => {