feat(tabs): 支持标签展示配置并提示保存 SQL 文件

- 新增标签展示元素配置,支持单行、双行布局和元素排序

- 在设置面板提供标签展示入口并持久化用户配置

- 标签右键菜单增加标签设置入口并优化悬浮信息展示

- 关闭外部 SQL 文件标签前检测未保存草稿并支持保存后关闭
This commit is contained in:
Syngnat
2026-06-02 11:16:25 +08:00
parent e6dd986115
commit c405eb08b5
11 changed files with 1664 additions and 60 deletions

View File

@@ -0,0 +1,37 @@
import { describe, expect, it } from 'vitest';
import {
getSQLFileTabPath,
hasSQLFileTabUnsavedChanges,
isSQLFileQueryTab,
normalizeSQLFileReadContent,
} from './sqlFileTabDirty';
describe('sqlFileTabDirty', () => {
it('only treats query tabs with filePath as SQL file tabs', () => {
expect(isSQLFileQueryTab({ type: 'query', filePath: '/tmp/a.sql' })).toBe(true);
expect(isSQLFileQueryTab({ type: 'query', filePath: ' ' })).toBe(false);
expect(isSQLFileQueryTab({ type: 'table', filePath: '/tmp/a.sql' } as any)).toBe(false);
expect(getSQLFileTabPath({ type: 'query', filePath: ' /tmp/a.sql ' })).toBe('/tmp/a.sql');
});
it('normalizes old and new SQL file read payloads', () => {
expect(normalizeSQLFileReadContent('select 1;')).toBe('select 1;');
expect(normalizeSQLFileReadContent({ content: 'select 2;', filePath: '/tmp/a.sql' })).toBe('select 2;');
expect(normalizeSQLFileReadContent({ isLargeFile: true, filePath: '/tmp/a.sql' })).toBe('');
});
it('detects unsaved changes by comparing tab query with disk content', () => {
expect(hasSQLFileTabUnsavedChanges({
type: 'query',
filePath: '/tmp/a.sql',
query: 'select 1;',
} as any, 'select 1;')).toBe(false);
expect(hasSQLFileTabUnsavedChanges({
type: 'query',
filePath: '/tmp/a.sql',
query: 'select 2;',
} as any, 'select 1;')).toBe(true);
});
});