mirror of
https://github.com/Syngnat/GoNavi.git
synced 2026-07-11 15:32:24 +08:00
✨ feat(connection): 增强连接管理与交互体验
- 新增测试连接功能,修复底层驱动假成功问题,确保密码/端口验证准确 - 支持导入/导出连接配置(JSON),便于迁移与备份 - 优化侧边栏:实现虚拟滚动解决卡顿,增加数据库筛选与断开连接重连机制 - 优化交互:改进右键菜单体验(全行触发/禁用选文),完善新建查询的上下文自动关联 - 界面调整:精简连接弹窗,移除冗余的默认数据库输入
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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),
|
||||
|
||||
Reference in New Issue
Block a user