From 90e8bbe757f3616bb100342a9ca640a060a4439e Mon Sep 17 00:00:00 2001 From: t8y2 <1156263951@qq.com> Date: Wed, 13 May 2026 13:50:48 +0800 Subject: [PATCH] perf(redis): paginate key scanning, relocate flush DB button - Replace do-while loop that scanned ALL keys with single-page scan - Add "Load More" button at bottom for incremental loading - Move flush DB button from search bar to command line area to reduce accidental clicks Closes #242 --- src/components/redis/RedisKeyBrowser.vue | 63 +++++++++++++++++------- 1 file changed, 45 insertions(+), 18 deletions(-) diff --git a/src/components/redis/RedisKeyBrowser.vue b/src/components/redis/RedisKeyBrowser.vue index 94761fcd3..808cc41bf 100644 --- a/src/components/redis/RedisKeyBrowser.vue +++ b/src/components/redis/RedisKeyBrowser.vue @@ -44,9 +44,11 @@ const props = defineProps<{ const flatKeys = ref([]); const treeKeys = ref([]); const loading = ref(false); +const loadingMore = ref(false); const searchPattern = ref("*"); const selectedKeyRaw = ref(null); const hasMore = ref(false); +const scanCursor = ref(0); const expandedGroupIds = ref>(new Set()); const checkedKeys = ref>(new Set()); const pendingDanger = ref< @@ -117,26 +119,44 @@ function rebuildTree(expandAll = false) { } } +async function scanNextPage() { + const result = await api.redisScanKeys( + props.connectionId, + props.db, + scanCursor.value, + effectivePattern.value, + PAGE_SIZE, + ); + const existingKeys = new Set(flatKeys.value.map((key) => key.key_raw)); + flatKeys.value = [...flatKeys.value, ...result.keys.filter((key) => !existingKeys.has(key.key_raw))]; + scanCursor.value = result.cursor; + hasMore.value = result.cursor !== 0; + rebuildTree(isSearchMode.value); +} + async function loadKeys() { loading.value = true; flatKeys.value = []; selectedKeyRaw.value = null; checkedKeys.value = new Set(); + scanCursor.value = 0; try { - let cur = 0; - do { - const result = await api.redisScanKeys(props.connectionId, props.db, cur, effectivePattern.value, PAGE_SIZE); - const existingKeys = new Set(flatKeys.value.map((key) => key.key_raw)); - flatKeys.value = [...flatKeys.value, ...result.keys.filter((key) => !existingKeys.has(key.key_raw))]; - cur = result.cursor; - hasMore.value = cur !== 0; - rebuildTree(isSearchMode.value); - } while (cur !== 0); + await scanNextPage(); } finally { loading.value = false; } } +async function loadMore() { + if (!hasMore.value || loadingMore.value) return; + loadingMore.value = true; + try { + await scanNextPage(); + } finally { + loadingMore.value = false; + } +} + function toggleGroup(groupId: string) { const next = new Set(expandedGroupIds.value); if (next.has(groupId)) next.delete(groupId); @@ -323,15 +343,6 @@ onMounted(loadKeys); - {{ loading && flatKeys.length === 0 ? t("redis.loadingKeys") : t("redis.keys", { count: flatKeys.length }) }} @@ -365,6 +376,16 @@ onMounted(loadKeys); +
+
@@ -482,6 +503,12 @@ onMounted(loadKeys);
+
+ +