| 1234567891011121314151617181920212223242526272829303132333435363738394041 |
- import { ref } from 'vue'
- /** 提交类按钮默认防抖间隔(毫秒) */
- export const ACTION_GUARD_DEBOUNCE_MS = 300
- /**
- * 提交/支付类操作:防抖 + 执行期间加锁(禁止重复点击)
- * @param {number} debounceMs 两次有效触发的最小间隔
- * @returns {{ locked: import('vue').Ref<boolean>, run: Function, wrap: Function }}
- */
- export function useActionGuard(debounceMs = ACTION_GUARD_DEBOUNCE_MS) {
- const locked = ref(false)
- let lastAt = 0
- /**
- * 在锁内执行异步任务;校验失败可在 task 内 return,仍会释放锁
- * @param {() => Promise<void|boolean>|void|boolean} task
- * @returns {Promise<boolean>} 是否实际执行了 task
- */
- async function run(task) {
- if (locked.value) return false
- const now = Date.now()
- if (now - lastAt < debounceMs) return false
- lastAt = now
- locked.value = true
- try {
- await task()
- return true
- } finally {
- locked.value = false
- }
- }
- /** 包装函数,适合直接绑 @click */
- function wrap(fn) {
- return (...args) => run(() => fn(...args))
- }
- return { locked, run, wrap }
- }
|