🐛 fix(sidebar): 修复视图定位慢加载误报

- 兼容 table-prefixed key 的视图兜底定位

- 区分对象树仍在加载与真实未找到状态

- 补充 sidebarLocate 与 Sidebar 定位回归测试
This commit is contained in:
Syngnat
2026-06-10 01:13:29 +08:00
parent 01d8fe44ce
commit cb90a4ad01
4 changed files with 56 additions and 4 deletions

View File

@@ -1452,5 +1452,7 @@ describe('Sidebar locate toolbar', () => {
expect(source).toContain('const SIDEBAR_LOCATE_LOAD_WAIT_ATTEMPTS = 160;');
expect(source).toContain('attempt < SIDEBAR_LOCATE_LOAD_WAIT_ATTEMPTS');
expect(source).toContain('window.setTimeout(resolve, SIDEBAR_LOCATE_LOAD_WAIT_INTERVAL_MS)');
expect(source).toContain('return !loadingNodesRef.current.has(loadKey);');
expect(source).toContain('对象仍在加载中');
});
});

View File

@@ -2445,10 +2445,11 @@ const Sidebar: React.FC<{
const locateObjectInSidebarRef = useRef<(detail: unknown) => Promise<void>>(async () => {});
const waitForSidebarLoadKey = async (loadKey: string) => {
const waitForSidebarLoadKey = async (loadKey: string): Promise<boolean> => {
for (let attempt = 0; attempt < SIDEBAR_LOCATE_LOAD_WAIT_ATTEMPTS && loadingNodesRef.current.has(loadKey); attempt += 1) {
await new Promise(resolve => window.setTimeout(resolve, SIDEBAR_LOCATE_LOAD_WAIT_INTERVAL_MS));
}
return !loadingNodesRef.current.has(loadKey);
};
const locateObjectInSidebar = async (detail: unknown) => {
@@ -2511,7 +2512,11 @@ const Sidebar: React.FC<{
return;
}
if (loadingNodesRef.current.has(dbLoadKey)) {
await waitForSidebarLoadKey(dbLoadKey);
const loaded = await waitForSidebarLoadKey(dbLoadKey);
if (!loaded) {
message.info(`数据库节点仍在加载中:${request.dbName},请稍后再试`);
return;
}
} else {
await loadDatabases(connectionNode);
}
@@ -2526,7 +2531,11 @@ const Sidebar: React.FC<{
path = findSidebarNodePathForLocate(treeDataRef.current as SidebarLocateTreeNodeLike[], target);
if (!path) {
if (loadingNodesRef.current.has(tableLoadKey)) {
await waitForSidebarLoadKey(tableLoadKey);
const loaded = await waitForSidebarLoadKey(tableLoadKey);
if (!loaded) {
message.info(`${objectLabel}所在数据库对象仍在加载中:${request.dbName},请稍后再试`);
return;
}
} else {
await loadTables(dbNode);
}

View File

@@ -660,6 +660,47 @@ describe('sidebarLocate', () => {
]);
});
it('falls back to a visual table-like node with a table-prefixed key for a view request', () => {
const target = resolveSidebarLocateTarget({
tabId: 'stale-view-tab-id',
connectionId: 'conn-1',
dbName: 'SYSDBA',
tableName: 'V_ACCOUNT',
objectGroup: 'views',
}, { groupBySchema: false });
const tree = [
{
key: 'conn-1',
children: [
{
key: 'conn-1-SYSDBA',
dataRef: { id: 'conn-1', dbName: 'SYSDBA' },
children: [
{
key: 'conn-1-SYSDBA-tables',
children: [
{
key: 'conn-1-SYSDBA-table-V_ACCOUNT',
type: 'table',
dataRef: {},
},
],
},
],
},
],
},
];
expect(findSidebarNodePathForLocate(tree, target)).toEqual([
'conn-1',
'conn-1-SYSDBA',
'conn-1-SYSDBA-tables',
'conn-1-SYSDBA-table-V_ACCOUNT',
]);
});
it('finds a view node by title when the tree node is missing object metadata', () => {
const target = resolveSidebarLocateTarget({
tabId: 'stale-view-tab-id',

View File

@@ -402,7 +402,7 @@ const getVisualNodeObjectName = (
? [`${target.databaseKey}-trigger-`]
: target.objectGroup === 'routines'
? [`${target.databaseKey}-routine-`]
: [`${target.databaseKey}-`];
: [`${target.databaseKey}-table-`, `${target.databaseKey}-`];
const matchedPrefix = keyPrefixes.find((prefix) => nodeKey.startsWith(prefix));
return matchedPrefix ? nodeKey.slice(matchedPrefix.length) : '';