101 lines
2.9 KiB
Go
101 lines
2.9 KiB
Go
package main
|
|
|
|
import (
|
|
"flag"
|
|
"log"
|
|
"photowall/internal/config"
|
|
"photowall/internal/database"
|
|
"photowall/internal/handler"
|
|
"photowall/internal/router"
|
|
"photowall/internal/scheduler"
|
|
"photowall/internal/service"
|
|
"photowall/pkg/jwt"
|
|
"photowall/pkg/redis"
|
|
"photowall/pkg/sensitive"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
func main() {
|
|
migrateFlag := flag.Bool("migrate", false, "执行数据库迁移与种子数据初始化 (AutoMigrate)")
|
|
flag.Parse()
|
|
|
|
// 1. 加载配置
|
|
cfg := config.Load()
|
|
if *migrateFlag {
|
|
cfg.DBAutoMigrate = true
|
|
}
|
|
log.Printf("[config] port=%s db=%s@%s:%s/%s auto_migrate=%v", cfg.Port, cfg.DBUser, cfg.DBHost, cfg.DBPort, cfg.DBName, cfg.DBAutoMigrate)
|
|
|
|
// 2. 初始化数据库(连接 MySQL;仅在开启 auto_migrate 时迁移和播种)
|
|
if err := database.Init(); err != nil {
|
|
log.Fatalf("[database] init failed: %v", err)
|
|
}
|
|
|
|
// 2.1 初始化 Redis(连接失败自动降级内存模式)
|
|
redis.Init(redis.Config{
|
|
Host: cfg.RedisHost,
|
|
Port: cfg.RedisPort,
|
|
Password: cfg.RedisPassword,
|
|
DB: cfg.RedisDB,
|
|
})
|
|
|
|
// 3. JWT
|
|
jm := jwt.New(cfg.JWTSecret, cfg.JWTExpireHrs)
|
|
|
|
// 4. 初始化 Service
|
|
configSvc := service.NewConfigService(database.DB)
|
|
if cfg.DBAutoMigrate {
|
|
// 初始化系统默认配置(逐条检测并补齐)
|
|
if err := configSvc.InitDefaults(); err != nil {
|
|
log.Printf("[config] init defaults failed: %v", err)
|
|
}
|
|
} else {
|
|
// 快速预热配置缓存(单次全量查询,跳过逐条校验)
|
|
configSvc.WarmUpCache()
|
|
}
|
|
|
|
authSvc := service.NewAuthService(database.DB, jm, configSvc)
|
|
userSvc := service.NewUserService(database.DB)
|
|
regionSvc := service.NewRegionService(database.DB)
|
|
schoolSvc := service.NewSchoolService(database.DB)
|
|
classSvc := service.NewClassService(database.DB, configSvc)
|
|
adminSvc := service.NewAdminService(database.DB)
|
|
menuSvc := service.NewMenuService(database.DB)
|
|
|
|
if cfg.DBAutoMigrate {
|
|
// 初始化默认菜单(逐条检测并补齐)
|
|
if err := menuSvc.InitDefaults(); err != nil {
|
|
log.Printf("[menu] init defaults failed: %v", err)
|
|
}
|
|
}
|
|
// 初始化敏感词过滤器
|
|
sensitive.Init(database.DB)
|
|
|
|
// 5. 初始化 Handler
|
|
deps := &router.Deps{
|
|
Auth: handler.NewAuthHandler(authSvc),
|
|
User: handler.NewUserHandler(userSvc),
|
|
Region: handler.NewRegionHandler(regionSvc),
|
|
School: handler.NewSchoolHandler(schoolSvc),
|
|
Class: handler.NewClassHandler(classSvc),
|
|
Admin: handler.NewAdminHandler(adminSvc),
|
|
Upload: handler.NewUploadHandler(database.DB),
|
|
Config: handler.NewConfigHandler(configSvc),
|
|
Menu: handler.NewMenuHandler(menuSvc),
|
|
}
|
|
|
|
// 6. 启动定时清理任务
|
|
scheduler.StartCleanup(adminSvc)
|
|
|
|
// 7. 启动 HTTP 服务
|
|
gin.SetMode(gin.ReleaseMode)
|
|
r := gin.Default()
|
|
router.Register(r, jm, deps)
|
|
|
|
log.Printf("[server] photowall API listening on :%s", cfg.Port)
|
|
if err := r.Run(":" + cfg.Port); err != nil {
|
|
log.Fatalf("[server] failed: %v", err)
|
|
}
|
|
}
|