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{}, &model.ModelInfo{}) // 4. 初始化 Repository dbRepo := repository.NewDatabaseRepository(db) subTableRepo := repository.NewSubTableRepository(db) modelRepo := repository.NewModelRepository(db) // 5. 初始化 Service dbService := service.NewDatabaseService(dbRepo, subTableRepo) subTableService := service.NewSubTableService(subTableRepo, dbRepo) neo4jService := service.NewNeo4jService(dbRepo) modelService := service.NewModelService(modelRepo) uploadService, err := service.NewUploadService(cfg) if err != nil { log.Printf("Warning: Failed to initialize upload service: %v (files will not be available)", err) } // 6. 初始化 Handler dbHandler := handler.NewDatabaseHandler(dbService) subTableHandler := handler.NewSubTableHandler(subTableService) neo4jHandler := handler.NewNeo4jHandler(neo4jService) modelHandler := handler.NewModelHandler(modelService) systemHandler := handler.NewSystemHandler() var uploadHandler *handler.UploadHandler if uploadService != nil { uploadHandler = handler.NewUploadHandler(uploadService) } // 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) databaseGroup.POST("/graph/save", dbHandler.SaveGraph) } // 子表映射管理模块 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) } // Neo4j 连接管理模块 neo4jGroup := r.Group("/neo4j") { neo4jGroup.POST("/check", neo4jHandler.Check) neo4jGroup.POST("/graphs", neo4jHandler.GetGraphs) neo4jGroup.POST("/nodes", neo4jHandler.GetNodes) neo4jGroup.POST("/relationships", neo4jHandler.GetRelationships) } // Model 管理模块 modelGroup := r.Group("/model") { modelGroup.GET("/list", modelHandler.List) modelGroup.POST("/test", modelHandler.Test) modelGroup.POST("/add", modelHandler.Create) modelGroup.GET("/:id", modelHandler.GetByID) modelGroup.PUT("/:id", modelHandler.Update) modelGroup.DELETE("/:id", modelHandler.Delete) } // 系统信息模块 r.GET("/system/info", systemHandler.GetSystemInfo) // 文件上传模块 if uploadHandler != nil { // 本地文件静态服务 if cfg.UploadMode == "local" { r.Static("/files", cfg.UploadLocalPath) } // 上传路由 r.POST("/upload", uploadHandler.Upload) r.DELETE("/upload/:filename", uploadHandler.Delete) } // 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) } }