修复图表时间和查询区间不匹配问题

This commit is contained in:
Alex Yang
2025-12-02 23:20:10 +08:00
commit 4d66bdf633
49 changed files with 16275 additions and 0 deletions

166
backend/main.go Normal file
View File

@@ -0,0 +1,166 @@
package main
import (
"fmt"
"log"
"os"
"github.com/gin-gonic/gin"
"github.com/monitor/backend/config"
"github.com/monitor/backend/internal/db"
"github.com/monitor/backend/internal/device"
"github.com/monitor/backend/internal/handler"
"github.com/monitor/backend/internal/storage"
)
// 检查配置文件是否存在
func configFileExists() bool {
configFile := os.Getenv("SERVER_CONFIG_FILE")
if configFile == "" {
configFile = "./config.json"
}
_, err := os.Stat(configFile)
return err == nil
}
// 检查数据库配置是否为默认值
func isDefaultDBConfig(cfg *config.Config) bool {
return cfg.DB.Host == "localhost" &&
cfg.DB.Port == 3306 &&
cfg.DB.Username == "root" &&
cfg.DB.Password == "" &&
cfg.DB.Database == "monitor"
}
// main 函数启动服务器
func main() {
// 配置日志:只输出必要的信息,禁用调试日志
log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)
log.SetOutput(os.Stdout)
// 加载配置
cfg, err := config.LoadConfig()
if err != nil {
log.Fatalf("Failed to load config: %v", err)
}
// 检查配置文件是否存在
if !configFileExists() {
// 生成配置文件
if err := config.SaveConfig(cfg); err != nil {
log.Fatalf("Failed to generate config file: %v", err)
}
// 退出并提示用户配置
fmt.Println("配置文件已生成, 请进行配置然后启动服务.")
os.Exit(0)
}
// 检查数据库配置是否为默认值
if isDefaultDBConfig(cfg) {
// 退出并提示用户配置
fmt.Println("检测到数据库为默认配置, 请进行配置然后启动服务.")
os.Exit(0)
}
// 创建存储实例
store := storage.NewStorage(cfg)
defer store.Close()
// 初始化数据库连接(内部使用,不对外暴露)
dbConfig := db.Config{
Type: cfg.DB.Type,
Host: cfg.DB.Host,
Port: cfg.DB.Port,
Username: cfg.DB.Username,
Password: cfg.DB.Password,
Database: cfg.DB.Database,
SSLMode: cfg.DB.SSLMode,
Charset: cfg.DB.Charset,
}
// 尝试连接数据库,如果连接失败,只记录警告,不影响服务器启动
database, err := db.NewDB(dbConfig)
if err != nil {
log.Printf("Warning: Failed to connect to database: %v", err)
log.Printf("Server will continue without database connection")
} else {
defer database.Close()
log.Printf("Database connection initialized successfully")
// 这里可以将database传递给需要使用的组件
// 例如handler.SetDB(database)
}
// 创建Gin引擎禁用调试模式
gin.SetMode(gin.ReleaseMode)
r := gin.New()
// 添加必要的中间件
r.Use(gin.Recovery())
// 禁用Gin的默认日志
r.Use(gin.LoggerWithWriter(gin.DefaultWriter, "/health"))
// 设置CORS
r.Use(func(c *gin.Context) {
c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
c.Writer.Header().Set("Access-Control-Allow-Credentials", "true")
c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, accept, origin, Cache-Control, X-Requested-With")
c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS, GET, PUT, DELETE")
if c.Request.Method == "OPTIONS" {
c.AbortWithStatus(204)
return
}
c.Next()
})
// 设置全局存储实例
handler.SetStorage(store)
// 初始化设备存储实例
var deviceStore device.Storage
if database != nil {
// 使用MySQL存储
mysqlStore, err := device.NewMySQLStorage(database.GetDB())
if err != nil {
log.Printf("Warning: Failed to create MySQL device storage: %v", err)
// 回退到内存存储
deviceStore = device.NewMemoryStorage()
} else {
log.Printf("MySQL device storage initialized successfully")
deviceStore = mysqlStore
}
} else {
// 使用内存存储
deviceStore = device.NewMemoryStorage()
log.Printf("Using in-memory device storage")
}
handler.SetDeviceStorage(deviceStore)
// 配置静态文件服务
// 从backend/static目录提供静态文件
// 先注册API路由再处理静态文件避免路由冲突
// 注册API路由
handler.RegisterRoutes(r)
// 处理所有未匹配的路由返回静态文件或index.html
r.NoRoute(func(c *gin.Context) {
// 尝试提供静态文件
file := c.Request.URL.Path
if file == "/" {
file = "/index.html"
}
// 从static目录提供文件
c.File("./static" + file)
})
// 启动服务器
addr := fmt.Sprintf(":%d", cfg.Server.Port)
log.Printf("Server starting on %s", addr)
log.Printf("Static files served from /root/monitor/frontend")
if err := r.Run(addr); err != nil {
log.Fatalf("Failed to start server: %v", err)
}
}