From 3497df033f6dab09abca7279ef5235378ee82546 Mon Sep 17 00:00:00 2001 From: zipg Date: Tue, 7 Jul 2026 16:19:29 +0800 Subject: [PATCH] feat(grid): support searching filter columns --- .../src/components/editor/AiAssistant.vue | 1 + apps/desktop/src/components/grid/DataGrid.vue | 53 +++++++++++++++++-- .../components/ui/select/SelectContent.vue | 8 +-- apps/desktop/src/i18n/locales/en.ts | 2 + apps/desktop/src/i18n/locales/es.ts | 2 + apps/desktop/src/i18n/locales/it.ts | 2 + apps/desktop/src/i18n/locales/ja.ts | 2 + apps/desktop/src/i18n/locales/pt-BR.ts | 2 + apps/desktop/src/i18n/locales/zh-CN.ts | 2 + apps/desktop/src/i18n/locales/zh-TW.ts | 2 + 10 files changed, 70 insertions(+), 6 deletions(-) diff --git a/apps/desktop/src/components/editor/AiAssistant.vue b/apps/desktop/src/components/editor/AiAssistant.vue index 15206d9e6d..e83f454cca 100644 --- a/apps/desktop/src/components/editor/AiAssistant.vue +++ b/apps/desktop/src/components/editor/AiAssistant.vue @@ -82,6 +82,7 @@ const queryStore = useQueryStore(); const { openTableTarget } = useNavigationTargets({ showFieldLineageDialog: ref(false), showDatabaseSearchDialog: ref(false), + showDiagramDialog: ref(false), }); const { toast } = useToast(); const { isDark } = useTheme(); diff --git a/apps/desktop/src/components/grid/DataGrid.vue b/apps/desktop/src/components/grid/DataGrid.vue index 235ac5f670..8e5fb89069 100644 --- a/apps/desktop/src/components/grid/DataGrid.vue +++ b/apps/desktop/src/components/grid/DataGrid.vue @@ -1080,6 +1080,7 @@ const serverFilterValueByKey = ref>(new Map()); let serverFilterRequestId = 0; let serverFilterSearchTimer: ReturnType | undefined; const filterBuilderOpen = ref(false); +const filterBuilderColumnSearch = ref(""); const filterModeOptions: Array<{ value: FilterMode; labelKey: string }> = [ { value: "equals", labelKey: "grid.filterBuilderEquals" }, { value: "not-equals", labelKey: "grid.filterBuilderNotEquals" }, @@ -1092,6 +1093,12 @@ const filterModeOptions: Array<{ value: FilterMode; labelKey: string }> = [ ]; const filterBuilderColumns = computed(() => props.tableMeta?.columns ?? []); const filterBuilderColumnOptions = computed(() => filterBuilderColumns.value.map((column) => column.name)); +const filteredFilterBuilderColumnOptions = computed(() => { + const query = filterBuilderColumnSearch.value.trim().toLowerCase(); + if (!query) return filterBuilderColumnOptions.value; + return filterBuilderColumnOptions.value.filter((columnName) => columnName.toLowerCase().includes(query)); +}); +const filterBuilderColumnSearchNavigationKeys = new Set(["Escape", "Tab", "ArrowUp", "ArrowDown", "Home", "End", "PageUp", "PageDown"]); const structuredFilterCacheKey = computed(() => props.cacheKey || [props.connectionId ?? "", props.database ?? "", props.context ?? "", props.tableMeta?.schema ?? "", props.tableMeta?.tableName ?? ""].join("\u0001")); const structuredFilterScopeKey = computed(() => [props.connectionId ?? "", props.database ?? "", props.schema ?? "", props.context ?? "", props.tableMeta?.schema ?? "", props.tableMeta?.tableName ?? "", filterBuilderColumnOptions.value.join("\0")].join("\u0001")); const structuredFilterRules = ref([]); @@ -1815,6 +1822,24 @@ function updateStructuredFilterRule(ruleId: string, patch: Partial 0 ? [defaultStructuredFilterRule()] : []; @@ -1871,6 +1896,10 @@ async function applyStructuredFilters() { watch([structuredFilterCacheKey, structuredFilterScopeKey], loadStructuredFilterStateForScope, { immediate: true }); +watch(filterBuilderOpen, (open) => { + if (!open) filterBuilderColumnSearch.value = ""; +}); + watch( [structuredFilterRules, appliedStructuredWhereInput], () => { @@ -8243,14 +8272,32 @@ const gridContextMenuItems = computed(() => {
- - - + + {{ columnName }} +
+ {{ t("grid.filterBuilderNoMatchingColumns") }} +
+
+ + +
diff --git a/apps/desktop/src/components/ui/select/SelectContent.vue b/apps/desktop/src/components/ui/select/SelectContent.vue index 01f880c081..a95ab328a5 100644 --- a/apps/desktop/src/components/ui/select/SelectContent.vue +++ b/apps/desktop/src/components/ui/select/SelectContent.vue @@ -16,17 +16,19 @@ const props = withDefaults( class?: HTMLAttributes["class"]; disablePortal?: boolean; disableOutsidePointerEvents?: boolean; + hideScrollButtons?: boolean; } >(), { position: "popper", disablePortal: false, disableOutsidePointerEvents: true, + hideScrollButtons: false, }, ); const emits = defineEmits(); -const delegatedProps = reactiveOmit(props, "class", "disablePortal"); +const delegatedProps = reactiveOmit(props, "class", "disablePortal", "hideScrollButtons"); const forwarded = useForwardPropsEmits(delegatedProps, emits); @@ -45,11 +47,11 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits); ) " > - + - +
diff --git a/apps/desktop/src/i18n/locales/en.ts b/apps/desktop/src/i18n/locales/en.ts index aaef3406ea..3d6fcef6f6 100644 --- a/apps/desktop/src/i18n/locales/en.ts +++ b/apps/desktop/src/i18n/locales/en.ts @@ -719,6 +719,8 @@ export default { filterBuilderSummary: "{count} rules", filterBuilderAddRule: "Add rule", filterBuilderColumn: "Column", + filterBuilderSearchColumns: "Search columns...", + filterBuilderNoMatchingColumns: "No matching columns", filterBuilderValue: "Value", filterBuilderNoValue: "No value needed", filterBuilderEmpty: "Add a rule to start filtering rows.", diff --git a/apps/desktop/src/i18n/locales/es.ts b/apps/desktop/src/i18n/locales/es.ts index cb3e19f6b0..cf1bfca546 100644 --- a/apps/desktop/src/i18n/locales/es.ts +++ b/apps/desktop/src/i18n/locales/es.ts @@ -919,6 +919,8 @@ export default withEnglishFallback({ }, sortUnsupported: "Este SQL no admite ordenamiento del resultado completo. Intenta con una consulta SELECT simple.", truncatedHint: "Los resultados están limitados a 10.000 filas. Usa LIMIT/OFFSET en tu consulta para paginar.", + filterBuilderSearchColumns: "Buscar columnas...", + filterBuilderNoMatchingColumns: "Sin columnas coincidentes", }, exportProgress: { title: "Exportando datos de la tabla", diff --git a/apps/desktop/src/i18n/locales/it.ts b/apps/desktop/src/i18n/locales/it.ts index 1570ecbfea..71783b9250 100644 --- a/apps/desktop/src/i18n/locales/it.ts +++ b/apps/desktop/src/i18n/locales/it.ts @@ -917,6 +917,8 @@ export default withEnglishFallback({ }, sortUnsupported: "Questo SQL non supporta l'ordinamento sull'intero risultato. Riprova con una query SELECT semplice.", truncatedHint: "Risultati troncati a {count} righe. Usa la paginazione a piè di pagina o regola le righe per pagina.", + filterBuilderSearchColumns: "Cerca campi...", + filterBuilderNoMatchingColumns: "Nessun campo corrispondente", }, exportProgress: { title: "Esportazione Dati Tabella", diff --git a/apps/desktop/src/i18n/locales/ja.ts b/apps/desktop/src/i18n/locales/ja.ts index c00e425c63..8b47efc19e 100644 --- a/apps/desktop/src/i18n/locales/ja.ts +++ b/apps/desktop/src/i18n/locales/ja.ts @@ -917,6 +917,8 @@ export default withEnglishFallback({ renderMode: "レンダーモード", undoChange: "変更を元に戻す", redoChange: "変更をやり直す", + filterBuilderSearchColumns: "フィールドを検索...", + filterBuilderNoMatchingColumns: "一致するフィールドがありません", }, exportProgress: { title: "テーブルデータをエクスポート中", diff --git a/apps/desktop/src/i18n/locales/pt-BR.ts b/apps/desktop/src/i18n/locales/pt-BR.ts index a9b710990a..6064582dd0 100644 --- a/apps/desktop/src/i18n/locales/pt-BR.ts +++ b/apps/desktop/src/i18n/locales/pt-BR.ts @@ -918,6 +918,8 @@ export default withEnglishFallback({ }, sortUnsupported: "Este SQL não suporta a ordenação do resultado completo. Tente novamente com uma única consulta SELECT.", truncatedHint: "Resultados truncados em {count} linhas. Use a paginação no rodapé ou ajuste as linhas por página.", + filterBuilderSearchColumns: "Pesquisar campos...", + filterBuilderNoMatchingColumns: "Nenhum campo correspondente", }, exportProgress: { title: "Exportando Dados da Tabela", diff --git a/apps/desktop/src/i18n/locales/zh-CN.ts b/apps/desktop/src/i18n/locales/zh-CN.ts index 27f688ed34..1a969cc4dd 100644 --- a/apps/desktop/src/i18n/locales/zh-CN.ts +++ b/apps/desktop/src/i18n/locales/zh-CN.ts @@ -721,6 +721,8 @@ export default withEnglishFallback({ filterBuilderSummary: "{count} 条规则", filterBuilderAddRule: "新增条件", filterBuilderColumn: "字段", + filterBuilderSearchColumns: "搜索字段...", + filterBuilderNoMatchingColumns: "没有匹配的字段", filterBuilderValue: "值", filterBuilderNoValue: "无需输入值", filterBuilderEmpty: "新增一条条件后即可开始筛选。", diff --git a/apps/desktop/src/i18n/locales/zh-TW.ts b/apps/desktop/src/i18n/locales/zh-TW.ts index 4d7080cc0a..a5de672708 100644 --- a/apps/desktop/src/i18n/locales/zh-TW.ts +++ b/apps/desktop/src/i18n/locales/zh-TW.ts @@ -918,6 +918,8 @@ export default withEnglishFallback({ }, sortUnsupported: "目前 SQL 不支援完整排序,請改為單條 SELECT 查詢後再嘗試。", truncatedHint: "結果已截斷,僅顯示前 {count} 行。可經由底部分頁繼續載入,或調整每頁行數。", + filterBuilderSearchColumns: "搜尋欄位...", + filterBuilderNoMatchingColumns: "沒有匹配的欄位", }, exportProgress: { title: "匯出資料表資料",