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, () => {