feat(connection): 增强连接管理与交互体验

- 新增测试连接功能,修复底层驱动假成功问题,确保密码/端口验证准确
- 支持导入/导出连接配置(JSON),便于迁移与备份
- 优化侧边栏:实现虚拟滚动解决卡顿,增加数据库筛选与断开连接重连机制
- 优化交互:改进右键菜单体验(全行触发/禁用选文),完善新建查询的上下文自动关联
- 界面调整:精简连接弹窗,移除冗余的默认数据库输入
This commit is contained in:
杨国锋
2026-02-02 16:33:11 +08:00
parent 7f201f9bcd
commit 4099796c88
15 changed files with 382 additions and 121 deletions

View File

@@ -40,7 +40,16 @@ func (a *App) Shutdown(ctx context.Context) {
// Helper: Generate a unique key for the connection config
func getCacheKey(config connection.ConnectionConfig) string {
return fmt.Sprintf("%s|%s|%s:%d|%s|%s|%v", config.Type, config.User, config.Host, config.Port, config.Database, config.SSH.Host, config.UseSSH)
sshPart := ""
if config.UseSSH {
sshPart = fmt.Sprintf("|ssh:%s@%s:%d|%s", config.SSH.User, config.SSH.Host, config.SSH.Port, config.SSH.KeyPath)
// We don't include SSH password in key string to avoid log exposure if key is logged,
// but for cache uniqueness it is critical.
// Let's include a hash or just the value if we assume internal use.
// Including value for correctness.
sshPart += "|" + config.SSH.Password
}
return fmt.Sprintf("%s|%s:%s@%s:%d|%s%s", config.Type, config.User, config.Password, config.Host, config.Port, config.Database, sshPart)
}
// Helper: Get or create a database connection

View File

@@ -28,7 +28,27 @@ func (a *App) DBConnect(config connection.ConnectionConfig) connection.QueryResu
return connection.QueryResult{Success: false, Message: err.Error()}
}
return connection.QueryResult{Success: true, Message: "Connected successfully"}
return connection.QueryResult{Success: true, Message: "连接成功"}
}
func (a *App) TestConnection(config connection.ConnectionConfig) connection.QueryResult {
// Force close existing cached connection if any to ensure fresh test
key := getCacheKey(config)
func() {
a.mu.Lock()
defer a.mu.Unlock()
if oldDB, ok := a.dbCache[key]; ok {
oldDB.Close()
delete(a.dbCache, key)
}
}()
_, err := a.getDatabase(config)
if err != nil {
return connection.QueryResult{Success: false, Message: err.Error()}
}
return connection.QueryResult{Success: true, Message: "连接成功"}
}
func (a *App) CreateDatabase(config connection.ConnectionConfig, dbName string) connection.QueryResult {

View File

@@ -44,6 +44,33 @@ func (a *App) OpenSQLFile() connection.QueryResult {
return connection.QueryResult{Success: true, Data: string(content)}
}
func (a *App) ImportConfigFile() connection.QueryResult {
selection, err := runtime.OpenFileDialog(a.ctx, runtime.OpenDialogOptions{
Title: "Select Config File",
Filters: []runtime.FileFilter{
{
DisplayName: "JSON Files (*.json)",
Pattern: "*.json",
},
},
})
if err != nil {
return connection.QueryResult{Success: false, Message: err.Error()}
}
if selection == "" {
return connection.QueryResult{Success: false, Message: "Cancelled"}
}
content, err := os.ReadFile(selection)
if err != nil {
return connection.QueryResult{Success: false, Message: err.Error()}
}
return connection.QueryResult{Success: true, Data: string(content)}
}
func (a *App) ImportData(config connection.ConnectionConfig, dbName, tableName string) connection.QueryResult {
selection, err := runtime.OpenFileDialog(a.ctx, runtime.OpenDialogOptions{
Title: fmt.Sprintf("Import into %s", tableName),