Skip to content

Commit cc71c6e

Browse files
pythonHuangclaude
andcommitted
fix: 数据库对象列表重复显示-后端元数据按名称去重+前端列表去重与加载序号守卫(慢网络竞态)+弹窗destroy-on-close
Co-Authored-By: Claude Code <noreply@anthropic.com>
1 parent a15afde commit cc71c6e

2 files changed

Lines changed: 28 additions & 5 deletions

File tree

‎Juggle.Application/Services/Impl/DataSourceService.cs‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,11 @@ public async Task<DbObjectsResult> GetDbObjectsAsync(string dataSourceName)
183183
throw new InvalidOperationException($"不支持的数据库类型: {dsInfo.DsType}");
184184
}
185185

186+
// 按名称去重(多 schema 同名对象、驱动重复返回等场景,避免前端列表重复显示)
187+
result.Tables = result.Tables.GroupBy(t => t.Name, StringComparer.OrdinalIgnoreCase).Select(g => g.First()).ToList();
188+
result.Views = result.Views.GroupBy(t => t.Name, StringComparer.OrdinalIgnoreCase).Select(g => g.First()).ToList();
189+
result.Procedures = result.Procedures.GroupBy(t => t.Name, StringComparer.OrdinalIgnoreCase).Select(g => g.First()).ToList();
190+
186191
return result;
187192
}
188193

‎JuggleNet6.Frontend/src/components/DbObjectBrowser.vue‎

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<template>
2-
<el-dialog :model-value="visible" @update:model-value="onVisibleChange" title="🗄 数据库对象(辅助生成 SQL)" width="1000px" append-to-body>
2+
<el-dialog :model-value="visible" @update:model-value="onVisibleChange" title="🗄 数据库对象(辅助生成 SQL)" width="1000px" append-to-body destroy-on-close>
33
<div style="display:flex;gap:10px">
44
<div style="flex:1;min-width:0">
55
<el-radio-group v-model="tab" size="small" @change="onTabChange">
@@ -105,6 +105,20 @@ const filteredObjects = computed(() => {
105105
return kw ? list.filter((o: any) => (o.name || '').toLowerCase().includes(kw)) : list
106106
})
107107
108+
/** 按名称去重(不区分大小写),防止重复加载或多 schema 同名导致列表重复显示 */
109+
function dedup(list: any[]): any[] {
110+
const seen = new Set<string>()
111+
return (list || []).filter((o: any) => {
112+
const key = (o.name || '').toLowerCase()
113+
if (!key || seen.has(key)) return false
114+
seen.add(key)
115+
return true
116+
})
117+
}
118+
119+
// 加载序号守卫:只应用最新一次请求的结果(防止慢网络下旧响应覆盖新数据)
120+
let loadSeq = 0
121+
108122
watch(() => props.visible, async v => {
109123
if (!v) return
110124
tab.value = 'tables'
@@ -114,12 +128,16 @@ watch(() => props.visible, async v => {
114128
procParams.value = []
115129
tables.value = []; views.value = []; procedures.value = []
116130
loading.value = true
131+
const seq = ++loadSeq
117132
try {
118133
const res: any = await request.post('/system/datasource/metadata', { dataSourceName: props.dataSourceName })
119-
tables.value = res.data?.tables || []
120-
views.value = res.data?.views || []
121-
procedures.value = res.data?.procedures || []
122-
} catch { /* 拦截器已提示 */ } finally { loading.value = false }
134+
if (seq !== loadSeq) return // 已有更新的加载,丢弃本次结果
135+
tables.value = dedup(res.data?.tables || [])
136+
views.value = dedup(res.data?.views || [])
137+
procedures.value = dedup(res.data?.procedures || [])
138+
} catch { /* 拦截器已提示 */ } finally {
139+
if (seq === loadSeq) loading.value = false
140+
}
123141
})
124142
125143
function onTabChange() {

0 commit comments

Comments
 (0)