feat: 重构前后端架构,添加Go后端和Python Agent服务
- 新增 Go 语言后端服务(server/),包含用户认证、Agent管理、数据库连接等API - 新增 Python Agent 服务(agent/),实现Agent核心逻辑和工具集 - 前端从原生HTML迁移到Vue.js框架(web/src/) - 添加 Docker Compose 支持(docker-compose.yml) - 添加项目架构文档(docs/ARCHITECTURE.md) - 添加环境变量示例(.env.example)和本地启动脚本(start-local.ps1) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
162
server/cmd/api/main.go
Normal file
162
server/cmd/api/main.go
Normal file
@@ -0,0 +1,162 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
"x-agents/server/internal/config"
|
||||
"x-agents/server/internal/handler"
|
||||
"x-agents/server/internal/model"
|
||||
"x-agents/server/internal/repository"
|
||||
"x-agents/server/internal/service"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// Logger 日志记录器
|
||||
type Logger struct {
|
||||
successLog *log.Logger
|
||||
errorLog *log.Logger
|
||||
}
|
||||
|
||||
func NewLogger() *Logger {
|
||||
// 创建日志目录
|
||||
today := time.Now().Format("2006-01-02")
|
||||
logDir := filepath.Join("logs", today)
|
||||
os.MkdirAll(logDir, 0755)
|
||||
|
||||
// 成功日志
|
||||
successFile, _ := os.OpenFile(filepath.Join(logDir, "success.log"), os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
|
||||
successLogger := log.New(successFile, "", log.Ldate|log.Ltime|log.Lshortfile)
|
||||
|
||||
// 错误日志
|
||||
errorFile, _ := os.OpenFile(filepath.Join(logDir, "failure.log"), os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
|
||||
errorLogger := log.New(errorFile, "", log.Ldate|log.Ltime|log.Lshortfile)
|
||||
|
||||
return &Logger{
|
||||
successLog: successLogger,
|
||||
errorLog: errorLogger,
|
||||
}
|
||||
}
|
||||
|
||||
// LogRequest 记录请求
|
||||
func (l *Logger) LogRequest(method, path, body string, status int, duration time.Duration) {
|
||||
entry := "[%s] %s %s %d %v"
|
||||
|
||||
if status >= 400 {
|
||||
l.errorLog.Printf(entry, method, path, body, status, duration)
|
||||
} else {
|
||||
l.successLog.Printf(entry, method, path, body, status, duration)
|
||||
}
|
||||
}
|
||||
|
||||
var logger *Logger
|
||||
|
||||
func main() {
|
||||
// 初始化日志
|
||||
logger = NewLogger()
|
||||
|
||||
// 1. 加载配置
|
||||
cfg := config.Load()
|
||||
log.Printf("=== Server starting, port=%s ===", cfg.Port)
|
||||
|
||||
// 2. 初始化数据库
|
||||
db, err := config.InitDB(cfg)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to connect database: %v", err)
|
||||
}
|
||||
|
||||
// 3. 自动迁移表
|
||||
db.AutoMigrate(&model.DatabaseInfo{}, &model.SubTableInfo{})
|
||||
|
||||
// 4. 初始化 Repository
|
||||
dbRepo := repository.NewDatabaseRepository(db)
|
||||
subTableRepo := repository.NewSubTableRepository(db)
|
||||
|
||||
// 5. 初始化 Service
|
||||
dbService := service.NewDatabaseService(dbRepo, subTableRepo)
|
||||
subTableService := service.NewSubTableService(subTableRepo, dbRepo)
|
||||
|
||||
// 6. 初始化 Handler
|
||||
dbHandler := handler.NewDatabaseHandler(dbService)
|
||||
subTableHandler := handler.NewSubTableHandler(subTableService)
|
||||
systemHandler := handler.NewSystemHandler()
|
||||
|
||||
// 7. 设置路由
|
||||
r := gin.New()
|
||||
|
||||
// 添加日志和恢复中间件
|
||||
r.Use(gin.Logger())
|
||||
r.Use(gin.Recovery())
|
||||
|
||||
// 请求日志中间件
|
||||
r.Use(func(c *gin.Context) {
|
||||
start := time.Now()
|
||||
path := c.Request.URL.Path
|
||||
|
||||
// 记录请求体
|
||||
var requestBody []byte
|
||||
if c.Request.Method == "POST" || c.Request.Method == "PUT" {
|
||||
requestBody, _ = io.ReadAll(c.Request.Body)
|
||||
c.Request.Body = io.NopCloser(bytes.NewBuffer(requestBody))
|
||||
}
|
||||
|
||||
c.Next()
|
||||
|
||||
// 记录响应日志
|
||||
latency := time.Since(start)
|
||||
status := c.Writer.Status()
|
||||
|
||||
// 使用日志系统记录
|
||||
logger.LogRequest(c.Request.Method, path, string(requestBody), status, latency)
|
||||
})
|
||||
|
||||
// CORS 中间件
|
||||
r.Use(func(c *gin.Context) {
|
||||
c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
c.Writer.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
|
||||
c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")
|
||||
|
||||
if c.Request.Method == "OPTIONS" {
|
||||
c.AbortWithStatus(204)
|
||||
return
|
||||
}
|
||||
|
||||
c.Next()
|
||||
})
|
||||
|
||||
// 数据库管理模块
|
||||
databaseGroup := r.Group("/database")
|
||||
{
|
||||
databaseGroup.GET("/list", dbHandler.List)
|
||||
databaseGroup.GET("/:id", dbHandler.GetByID)
|
||||
databaseGroup.POST("/check", dbHandler.Check)
|
||||
databaseGroup.POST("/add", dbHandler.Create)
|
||||
databaseGroup.PUT("/:id", dbHandler.Update)
|
||||
databaseGroup.DELETE("/:id", dbHandler.Delete)
|
||||
}
|
||||
|
||||
// 子表映射管理模块
|
||||
subTableGroup := r.Group("/sub-table")
|
||||
{
|
||||
subTableGroup.POST("/add", subTableHandler.Create)
|
||||
subTableGroup.GET("/:id", subTableHandler.GetByID)
|
||||
subTableGroup.GET("/database/:database_id", subTableHandler.ListByDatabase)
|
||||
subTableGroup.GET("/mapping/:database_id", subTableHandler.GetMappingFromFile)
|
||||
subTableGroup.GET("/ddl/:database_id", subTableHandler.GetTablesDDL)
|
||||
subTableGroup.PUT("/:id", subTableHandler.Update)
|
||||
subTableGroup.DELETE("/:id", subTableHandler.Delete)
|
||||
}
|
||||
|
||||
// 系统信息模块
|
||||
r.GET("/system/info", systemHandler.GetSystemInfo)
|
||||
|
||||
// 8. 启动服务
|
||||
log.Printf("Server starting on :%s", cfg.Port)
|
||||
if err := r.Run(":" + cfg.Port); err != nil {
|
||||
log.Fatalf("Failed to start server: %v", err)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user