Private
Public Access
1
0

新增:连接管理、数据查询等功能

This commit is contained in:
2026-01-22 18:34:59 +08:00
parent 95d3a20292
commit 652f5e5d60
87 changed files with 15082 additions and 162 deletions

View File

@@ -0,0 +1,109 @@
package api
import (
"go-desk/internal/service"
"go-desk/internal/storage/models"
)
// ConnectionAPI 连接管理API
type ConnectionAPI struct {
connService *service.ConnectionService
}
// NewConnectionAPI 创建连接管理API
func NewConnectionAPI() (*ConnectionAPI, error) {
connService, err := service.NewConnectionService()
if err != nil {
return nil, err
}
return &ConnectionAPI{connService}, nil
}
// SaveConnectionRequest 保存连接请求结构体
type SaveConnectionRequest struct {
ID uint `json:"id"`
Name string `json:"name"`
Type string `json:"type"`
Host string `json:"host"`
Port int `json:"port"`
Username string `json:"username"`
Password string `json:"password"`
Database string `json:"database"`
Options string `json:"options"`
}
// SaveDbConnection 保存数据库连接配置
func (api *ConnectionAPI) SaveDbConnection(req SaveConnectionRequest) error {
conn := &models.DbConnection{
ID: req.ID,
Name: req.Name,
Type: req.Type,
Host: req.Host,
Port: req.Port,
Username: req.Username,
Password: req.Password,
Database: req.Database,
Options: req.Options,
}
return api.connService.SaveConnection(conn)
}
// ListDbConnections 获取连接列表
func (api *ConnectionAPI) ListDbConnections() ([]map[string]interface{}, error) {
connections, err := api.connService.ListConnections()
if err != nil {
return nil, err
}
result := make([]map[string]interface{}, len(connections))
timeFormat := "2006-01-02 15:04:05"
for i, conn := range connections {
result[i] = map[string]interface{}{
"id": conn.ID,
"name": conn.Name,
"type": conn.Type,
"host": conn.Host,
"port": conn.Port,
"username": conn.Username,
"database": conn.Database,
"options": conn.Options,
"created_at": conn.CreatedAt.Format(timeFormat),
"updated_at": conn.UpdatedAt.Format(timeFormat),
}
}
return result, nil
}
func (api *ConnectionAPI) DeleteDbConnection(id uint) error {
return api.connService.DeleteConnection(id)
}
func (api *ConnectionAPI) TestDbConnection(id uint) error {
return api.connService.TestConnection(id)
}
// TestConnectionRequest 测试连接请求结构体(不保存数据)
type TestConnectionRequest struct {
ID uint `json:"id"` // 编辑模式下的连接ID用于获取已保存的密码
Type string `json:"type"`
Host string `json:"host"`
Port int `json:"port"`
Username string `json:"username"`
Password string `json:"password"`
Database string `json:"database"`
Options string `json:"options"`
}
// TestDbConnectionWithParams 测试数据库连接(直接传入参数,不保存数据)
func (api *ConnectionAPI) TestDbConnectionWithParams(req TestConnectionRequest) error {
return api.connService.TestConnectionWithParams(
req.Type,
req.Host,
req.Port,
req.Username,
req.Password,
req.Database,
req.Options,
req.ID,
)
}

137
internal/api/sql_api.go Normal file
View File

@@ -0,0 +1,137 @@
package api
import (
"encoding/json"
"go-desk/internal/service"
"go-desk/internal/storage/models"
"go-desk/internal/storage/repository"
)
type SqlAPI struct {
sqlService *service.SqlExecService
resultRepo repository.ResultRepository
}
func NewSqlAPI() (*SqlAPI, error) {
sqlService, err := service.NewSqlExecService()
if err != nil {
return nil, err
}
resultRepo, err := repository.NewResultRepository()
if err != nil {
return nil, err
}
return &SqlAPI{sqlService, resultRepo}, nil
}
// ExecuteSQL 执行SQL语句
// 注意SQL 语句应该已经包含分页信息LIMIT 和 OFFSET由客户端添加
func (api *SqlAPI) ExecuteSQL(connectionID uint, sqlStr string, database string) (map[string]interface{}, error) {
result, err := api.sqlService.ExecuteSQL(connectionID, sqlStr, database)
if err != nil {
return nil, err
}
response := map[string]interface{}{
"type": result.Type,
"data": result.Data,
"rowsAffected": result.RowsAffected,
"executionTime": result.ExecutionTime,
}
// 如果是查询,添加列顺序信息
if result.Type == "query" && len(result.Columns) > 0 {
response["columns"] = result.Columns
}
// 自动保存结果到历史记录(异步执行)
go func() {
api.resultRepo.Save(connectionID, database, sqlStr, result.Type, result.Data, result.Columns, result.RowsAffected, result.ExecutionTime)
}()
return response, nil
}
func (api *SqlAPI) GetDatabases(connectionID uint) ([]string, error) {
return api.sqlService.GetDatabases(connectionID)
}
func (api *SqlAPI) GetTables(connectionID uint, database string) ([]string, error) {
return api.sqlService.GetTables(connectionID, database)
}
func (api *SqlAPI) GetTableStructure(connectionID uint, database, tableName string) (map[string]interface{}, error) {
return api.sqlService.GetTableStructure(connectionID, database, tableName)
}
func (api *SqlAPI) GetIndexes(connectionID uint, database, tableName string) ([]map[string]interface{}, error) {
return api.sqlService.GetIndexes(connectionID, database, tableName)
}
func (api *SqlAPI) PreviewTableStructure(connectionID uint, database, tableName string, structure map[string]interface{}) ([]string, error) {
return api.sqlService.PreviewTableStructure(connectionID, database, tableName, structure)
}
func (api *SqlAPI) UpdateTableStructure(connectionID uint, database, tableName string, structure map[string]interface{}) ([]string, error) {
return api.sqlService.UpdateTableStructure(connectionID, database, tableName, structure)
}
func (api *SqlAPI) SaveResult(connectionID uint, database, sql string, resultType string, data interface{}, columns []string, rowsAffected int, executionTime int64) (map[string]interface{}, error) {
history, err := api.resultRepo.Save(connectionID, database, sql, resultType, data, columns, rowsAffected, executionTime)
if err != nil {
return nil, err
}
return historyToMap(history), nil
}
func (api *SqlAPI) GetResultHistory(connectionID *uint, keyword string, limit, offset int) (map[string]interface{}, error) {
histories, total, err := api.resultRepo.Search(connectionID, keyword, limit, offset)
if err != nil {
return nil, err
}
items := make([]map[string]interface{}, len(histories))
for i, h := range histories {
items[i] = historyToMap(&h)
}
return map[string]interface{}{"items": items, "total": total}, nil
}
func (api *SqlAPI) GetResultHistoryByID(id uint) (map[string]interface{}, error) {
history, err := api.resultRepo.FindByID(id)
if err != nil || history == nil {
return nil, err
}
return historyToMap(history), nil
}
func (api *SqlAPI) DeleteResultHistory(id uint) error {
return api.resultRepo.Delete(id)
}
func historyToMap(history *models.SqlResultHistory) map[string]interface{} {
result := map[string]interface{}{
"id": history.ID,
"connection_id": history.ConnectionID,
"database": history.Database,
"sql": history.Sql,
"type": history.Type,
"rows_affected": history.RowsAffected,
"execution_time": history.ExecutionTime,
"created_at": history.CreatedAt,
}
if history.Data != "" {
var data interface{}
json.Unmarshal([]byte(history.Data), &data)
result["data"] = data
}
if history.Columns != "" {
var columns []string
json.Unmarshal([]byte(history.Columns), &columns)
result["columns"] = columns
}
return result
}

79
internal/api/tab_api.go Normal file
View File

@@ -0,0 +1,79 @@
package api
import (
"fmt"
"go-desk/internal/service"
"go-desk/internal/storage/models"
)
// TabAPI 标签页API
type TabAPI struct {
tabService *service.TabService
}
// NewTabAPI 创建标签页API
func NewTabAPI() (*TabAPI, error) {
tabService, err := service.NewTabService()
if err != nil {
return nil, err
}
return &TabAPI{tabService: tabService}, nil
}
// SaveSqlTabs 保存SQL标签页列表接收 map 格式,转换为模型)
func (api *TabAPI) SaveSqlTabs(tabs []map[string]interface{}) error {
sqlTabs := make([]models.SqlTab, len(tabs))
for idx, tabData := range tabs {
tab := models.SqlTab{
Order: idx,
}
// 处理 ID
if id, ok := tabData["id"].(float64); ok && id > 0 {
tab.ID = uint(id)
}
// 处理标题
if title, ok := tabData["title"].(string); ok {
tab.Title = title
} else {
tab.Title = fmt.Sprintf("查询 %d", idx+1)
}
// 处理内容
if content, ok := tabData["content"].(string); ok {
tab.Content = content
}
// 处理连接ID
if connId, ok := tabData["connectionId"].(float64); ok && connId > 0 {
connID := uint(connId)
tab.ConnectionID = &connID
}
sqlTabs[idx] = tab
}
return api.tabService.SaveTabs(sqlTabs)
}
// ListSqlTabs 获取SQL标签页列表返回 map 格式)
func (api *TabAPI) ListSqlTabs() ([]map[string]interface{}, error) {
tabs, err := api.tabService.ListTabs()
if err != nil {
return nil, err
}
result := make([]map[string]interface{}, len(tabs))
for i, tab := range tabs {
result[i] = map[string]interface{}{
"id": tab.ID,
"title": tab.Title,
"content": tab.Content,
"connectionId": tab.ConnectionID,
"order": tab.Order,
"createdAt": tab.CreatedAt.Format("2006-01-02 15:04:05"),
"updatedAt": tab.UpdatedAt.Format("2006-01-02 15:04:05"),
}
}
return result, nil
}