fix(structure): 允许清除已删除字段的索引引用

Co-authored-by: zipg <4047349+zipg@users.noreply.github.com>
This commit is contained in:
zipg 2026-08-05 23:57:30 +08:00 committed by GitHub
parent e1822cb704
commit 51dedaa5b7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 23 additions and 7 deletions

View File

@ -55,6 +55,7 @@ import {
dataTypeLengthInputValue,
dataTypeLengthUnitValue,
defaultNewColumnDataType,
filterStructureIndexColumnOptions,
generateIndexName,
generateUniqueIndexName,
getColumnEditorControls,
@ -2108,11 +2109,10 @@ const availableColumnNames = computed(() =>
);
const colSearch = ref("");
const filteredColumnNames = computed(() => {
const q = colSearch.value.toLowerCase().trim();
if (!q) return availableColumnNames.value;
return availableColumnNames.value.filter((c) => c.toLowerCase().includes(q));
});
function filteredIndexColumnNames(selectedColumns: readonly string[]): string[] {
return filterStructureIndexColumnOptions(availableColumnNames.value, selectedColumns, colSearch.value);
}
function toggleIndexColumn(index: EditableStructureIndex, col: string) {
const previousColumns = [...index.columns];
@ -3163,7 +3163,7 @@ watch([activeTab, ddlLoading], ([tab, loading]) => {
<div class="px-[var(--structure-cell-px)] pb-1 pt-0.5">
<Input v-model="colSearch" :class="structureControlClass" :placeholder="t('grid.search')" @click.stop />
</div>
<DropdownMenuCheckboxItem v-for="col in filteredColumnNames" :key="col" :checked="index.columns.includes(col)" :class="index.columns.includes(col) ? 'bg-primary/10' : ''" @select.prevent @click="toggleIndexColumn(index, col)">
<DropdownMenuCheckboxItem v-for="col in filteredIndexColumnNames(index.columns)" :key="col" :checked="index.columns.includes(col)" :class="index.columns.includes(col) ? 'bg-primary/10' : ''" @select.prevent @click="toggleIndexColumn(index, col)">
{{ col }}
</DropdownMenuCheckboxItem>
</DropdownMenuContent>
@ -3199,7 +3199,7 @@ watch([activeTab, ddlLoading], ([tab, loading]) => {
<div class="px-[var(--structure-cell-px)] pb-1 pt-0.5">
<Input v-model="colSearch" :class="structureControlClass" :placeholder="t('grid.search')" @click.stop />
</div>
<DropdownMenuCheckboxItem v-for="col in filteredColumnNames" :key="col" :checked="index.includedColumns.includes(col)" :class="index.includedColumns.includes(col) ? 'bg-primary/10' : ''" @select.prevent @click="toggleIncludedColumn(index, col)">
<DropdownMenuCheckboxItem v-for="col in filteredIndexColumnNames(index.includedColumns)" :key="col" :checked="index.includedColumns.includes(col)" :class="index.includedColumns.includes(col) ? 'bg-primary/10' : ''" @select.prevent @click="toggleIncludedColumn(index, col)">
{{ col }}
</DropdownMenuCheckboxItem>
</DropdownMenuContent>

View File

@ -777,6 +777,15 @@ export function sameStructureIndexType(left: string | null | undefined, right: s
return normalizeStructureIndexType(left) === normalizeStructureIndexType(right);
}
/** Keep selected fields removable even after they are no longer available on the table. */
export function filterStructureIndexColumnOptions(availableColumns: readonly string[], selectedColumns: readonly string[], search = ""): string[] {
const availableSet = new Set(availableColumns);
const unavailableSelected = selectedColumns.filter((column) => column.trim() && !availableSet.has(column));
const options = [...new Set([...unavailableSelected, ...availableColumns])];
const query = search.trim().toLowerCase();
return query ? options.filter((column) => column.toLowerCase().includes(query)) : options;
}
export function createIndexDrafts(indexes: IndexInfo[]): EditableStructureIndex[] {
return indexes.map((index) => ({
id: `existing:${index.name}`,

View File

@ -9,6 +9,7 @@ import {
createColumnDrafts,
createIndexDrafts,
dataTypeLengthInputValue,
filterStructureIndexColumnOptions,
generateIndexName,
generateUniqueIndexName,
getColumnEditorControls,
@ -404,6 +405,12 @@ test("creates editable index drafts and splits pasted column lists", () => {
assert.equal(toColumnNames(["id", "name"]), "id, name");
});
test("keeps unavailable selected index fields removable", () => {
assert.deepEqual(filterStructureIndexColumnOptions(["id", "customer_id", "name"], ["platform_code"]), ["platform_code", "id", "customer_id", "name"]);
assert.deepEqual(filterStructureIndexColumnOptions(["id", "customer_id", "name"], ["customer_id", "platform_code"]), ["platform_code", "id", "customer_id", "name"]);
assert.deepEqual(filterStructureIndexColumnOptions(["id", "customer_id", "name"], ["platform_code"], "PLAT"), ["platform_code"]);
});
test("normalizes Postgres lowercase index types when creating structure drafts", () => {
const postgresIndexes: IndexInfo[] = [
{