feat(objects): search table fields by comment

This commit is contained in:
LRcoding 2026-07-17 00:11:16 +08:00 committed by GitHub
parent 63ea5f1fd8
commit 17747f8a2d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 63 additions and 5 deletions

View File

@ -94,6 +94,7 @@ import {
type ObjectBrowserSortKey,
} from "@/lib/table/objectBrowserRows";
import { resolveRowClickAction, shouldDeferSingleClick, type ObjectBrowserRowAction } from "@/lib/table/objectBrowserRowAction";
import { filterObjectBrowserTableColumns } from "@/lib/table/objectBrowserTableInfo";
import { createSidePanelRequestGuard } from "@/lib/table/sidePanelRequestGuard";
import { runBatchTableTruncate } from "@/lib/table/batchTableTruncate";
import { tableColumnDefaultDisplayValue } from "@/lib/table/tableColumnDefaultPresentation";
@ -777,11 +778,7 @@ const tableInfoTabListStyle = computed(() => ({
gridTemplateColumns: `repeat(${tableInfoTabs.value.length}, minmax(0, 1fr))`,
}));
const filteredTableColumns = computed(() => {
if (!tableInfoSearchQuery.value) return tableColumns.value;
const q = tableInfoSearchQuery.value.toLowerCase();
return tableColumns.value.filter((c) => c.name.toLowerCase().includes(q) || c.data_type.toLowerCase().includes(q));
});
const filteredTableColumns = computed(() => filterObjectBrowserTableColumns(tableColumns.value, tableInfoSearchQuery.value));
const filteredTableIndexes = computed(() => {
if (!tableInfoSearchQuery.value) return tableIndexes.value;

View File

@ -0,0 +1,13 @@
type SearchableTableInfoColumn = {
name: string;
data_type: string;
comment?: string | null;
};
/** Keep table-info search aligned with the name, type, and comment text visible in the field list. */
export function filterObjectBrowserTableColumns<T extends SearchableTableInfoColumn>(columns: T[], query: string): T[] {
const normalizedQuery = query.trim().toLocaleLowerCase();
if (!normalizedQuery) return columns;
return columns.filter((column) => [column.name, column.data_type, column.comment].some((value) => typeof value === "string" && value.toLocaleLowerCase().includes(normalizedQuery)));
}

View File

@ -0,0 +1,48 @@
import { strict as assert } from "node:assert";
import { test } from "vitest";
import { filterObjectBrowserTableColumns } from "../../apps/desktop/src/lib/table/objectBrowserTableInfo.ts";
const columns = [
{ name: "business_id", data_type: "varchar(64)", comment: "业务ID" },
{ name: "created_at", data_type: "TIMESTAMP", comment: "Created time" },
{ name: "status", data_type: "INT", comment: null },
{ name: "note", data_type: "TEXT" },
{ name: "empty_note", data_type: "TEXT", comment: "" },
];
test("filters table-info columns by case-insensitive name and trimmed type text", () => {
assert.deepEqual(
filterObjectBrowserTableColumns(columns, "BUSINESS").map((column) => column.name),
["business_id"],
);
assert.deepEqual(
filterObjectBrowserTableColumns(columns, " timestamp ").map((column) => column.name),
["created_at"],
);
});
test("filters table-info columns by partial localized and case-insensitive comments", () => {
assert.deepEqual(
filterObjectBrowserTableColumns(columns, "业务").map((column) => column.name),
["business_id"],
);
assert.deepEqual(
filterObjectBrowserTableColumns(columns, "CREATED TIME").map((column) => column.name),
["created_at"],
);
});
test("handles missing, null, and empty comments without changing no-match behavior", () => {
assert.deepEqual(filterObjectBrowserTableColumns(columns, "not present"), []);
});
test("returns every column for empty searches and preserves match order", () => {
assert.deepEqual(
filterObjectBrowserTableColumns(columns, " ").map((column) => column.name),
columns.map((column) => column.name),
);
assert.deepEqual(
filterObjectBrowserTableColumns(columns, "text").map((column) => column.name),
["note", "empty_note"],
);
});