From 2a2b4c639e503273ef6b4cc00cd8de9f9bcbcdf4 Mon Sep 17 00:00:00 2001 From: houhuan Date: Tue, 12 May 2026 21:19:30 +0800 Subject: [PATCH] refactor: extract useDebounce composable from 4 duplicate copies Co-Authored-By: Claude Opus 4.7 --- web/frontend/src/composables/useDebounce.ts | 9 +++++++++ web/frontend/src/views/Barcodes.vue | 12 +----------- web/frontend/src/views/Logs.vue | 11 +---------- web/frontend/src/views/Memory.vue | 12 +----------- web/frontend/src/views/Tasks.vue | 11 +---------- 5 files changed, 13 insertions(+), 42 deletions(-) create mode 100644 web/frontend/src/composables/useDebounce.ts diff --git a/web/frontend/src/composables/useDebounce.ts b/web/frontend/src/composables/useDebounce.ts new file mode 100644 index 0000000..5110de4 --- /dev/null +++ b/web/frontend/src/composables/useDebounce.ts @@ -0,0 +1,9 @@ +export function useDebounce any>(fn: T, delay: number) { + let timer: ReturnType | null = null + const debounced = (...args: Parameters) => { + if (timer) clearTimeout(timer) + timer = setTimeout(() => fn(...args), delay) + } + const cancel = () => { if (timer) clearTimeout(timer) } + return { debounced, cancel } +} diff --git a/web/frontend/src/views/Barcodes.vue b/web/frontend/src/views/Barcodes.vue index 7b86292..44eef29 100644 --- a/web/frontend/src/views/Barcodes.vue +++ b/web/frontend/src/views/Barcodes.vue @@ -185,17 +185,7 @@ import { ref, reactive, computed, onMounted, onUnmounted } from 'vue' import { ElMessage, ElMessageBox } from 'element-plus' import { Search, Refresh, Plus, Connection, Right, Setting } from '@element-plus/icons-vue' import api from '../api' - -// Debounce helper -function useDebounce any>(fn: T, delay: number) { - let timer: ReturnType | null = null - const debounced = (...args: Parameters) => { - if (timer) clearTimeout(timer) - timer = setTimeout(() => fn(...args), delay) - } - const cancel = () => { if (timer) clearTimeout(timer) } - return { debounced, cancel } -} +import { useDebounce } from '../composables/useDebounce' const loading = ref(false) const search = ref('') diff --git a/web/frontend/src/views/Logs.vue b/web/frontend/src/views/Logs.vue index 494dbce..66d2516 100644 --- a/web/frontend/src/views/Logs.vue +++ b/web/frontend/src/views/Logs.vue @@ -103,16 +103,7 @@ import { ref, reactive, onMounted, onUnmounted } from 'vue' import { ElMessage } from 'element-plus' import { Notebook, Warning, Timer, Search, Refresh } from '@element-plus/icons-vue' import api from '../api' - -function useDebounce any>(fn: T, delay: number) { - let timer: ReturnType | null = null - const debounced = (...args: Parameters) => { - if (timer) clearTimeout(timer) - timer = setTimeout(() => fn(...args), delay) - } - const cancel = () => { if (timer) clearTimeout(timer) } - return { debounced, cancel } -} +import { useDebounce } from '../composables/useDebounce' const loading = ref(false) const searchPath = ref('') diff --git a/web/frontend/src/views/Memory.vue b/web/frontend/src/views/Memory.vue index 168c2d1..7c0f4e3 100644 --- a/web/frontend/src/views/Memory.vue +++ b/web/frontend/src/views/Memory.vue @@ -161,17 +161,7 @@ import { ref, reactive, computed, onMounted, onUnmounted } from 'vue' import { ElMessage, ElMessageBox } from 'element-plus' import { Search, Refresh, Memo, CircleCheck, Warning } from '@element-plus/icons-vue' import api from '../api' - -// Debounce utility -function useDebounce any>(fn: T, delay: number) { - let timer: ReturnType | null = null - const debounced = (...args: Parameters) => { - if (timer) clearTimeout(timer) - timer = setTimeout(() => fn(...args), delay) - } - const cancel = () => { if (timer) clearTimeout(timer) } - return { debounced, cancel } -} +import { useDebounce } from '../composables/useDebounce' const loading = ref(false) const search = ref('') diff --git a/web/frontend/src/views/Tasks.vue b/web/frontend/src/views/Tasks.vue index 6d614c5..29a29dc 100644 --- a/web/frontend/src/views/Tasks.vue +++ b/web/frontend/src/views/Tasks.vue @@ -140,16 +140,7 @@ import { ref, reactive, onMounted, onUnmounted } from 'vue' import { ElMessage } from 'element-plus' import { Timer, CircleCheck, CircleClose, Loading, Search, Refresh } from '@element-plus/icons-vue' import api from '../api' - -function useDebounce any>(fn: T, delay: number) { - let timer: ReturnType | null = null - const debounced = (...args: Parameters) => { - if (timer) clearTimeout(timer) - timer = setTimeout(() => fn(...args), delay) - } - const cancel = () => { if (timer) clearTimeout(timer) } - return { debounced, cancel } -} +import { useDebounce } from '../composables/useDebounce' const loading = ref(false) const search = ref('')