| 
									
										
										
										
											2025-06-30 19:21:56 +08:00
										 |  |  | package app | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"fmt" | 
					
						
							|  |  |  | 	"os" | 
					
						
							|  |  |  | 	"os/signal" | 
					
						
							|  |  |  | 	"syscall" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	"go.uber.org/zap" | 
					
						
							|  |  |  | 	"gorm.io/gorm" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	"tyapi-server/internal/config" | 
					
						
							|  |  |  | 	"tyapi-server/internal/container" | 
					
						
							|  |  |  | 	"tyapi-server/internal/domains/user/entities" | 
					
						
							| 
									
										
										
										
											2025-07-11 21:05:58 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// 认证域实体 | 
					
						
							|  |  |  | 	certEntities "tyapi-server/internal/domains/certification/entities" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// 财务域实体 | 
					
						
							|  |  |  | 	financeEntities "tyapi-server/internal/domains/finance/entities" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-20 20:53:26 +08:00
										 |  |  | 	// 产品域实体 | 
					
						
							|  |  |  | 	productEntities "tyapi-server/internal/domains/product/entities" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  | 	apiEntities "tyapi-server/internal/domains/api/entities" | 
					
						
							| 
									
										
										
										
											2025-07-13 16:36:20 +08:00
										 |  |  | 	"tyapi-server/internal/infrastructure/database" | 
					
						
							| 
									
										
										
										
											2025-06-30 19:21:56 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Application 应用程序结构 | 
					
						
							|  |  |  | type Application struct { | 
					
						
							|  |  |  | 	container *container.Container | 
					
						
							|  |  |  | 	config    *config.Config | 
					
						
							|  |  |  | 	logger    *zap.Logger | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // NewApplication 创建新的应用程序实例 | 
					
						
							|  |  |  | func NewApplication() (*Application, error) { | 
					
						
							|  |  |  | 	// 加载配置 | 
					
						
							|  |  |  | 	cfg, err := config.LoadConfig() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, fmt.Errorf("failed to load config: %w", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// 创建日志器 | 
					
						
							|  |  |  | 	logger, err := createLogger(cfg) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, fmt.Errorf("failed to create logger: %w", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// 创建容器 | 
					
						
							|  |  |  | 	cont := container.NewContainer() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return &Application{ | 
					
						
							|  |  |  | 		container: cont, | 
					
						
							|  |  |  | 		config:    cfg, | 
					
						
							|  |  |  | 		logger:    logger, | 
					
						
							|  |  |  | 	}, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Run 运行应用程序 | 
					
						
							|  |  |  | func (a *Application) Run() error { | 
					
						
							|  |  |  | 	// 打印启动信息 | 
					
						
							|  |  |  | 	a.printBanner() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-02 16:17:59 +08:00
										 |  |  | 	// 检查是否需要自动迁移 | 
					
						
							|  |  |  | 	if a.config.Database.AutoMigrate { | 
					
						
							|  |  |  | 		a.logger.Info("Auto migration is enabled, running database migrations...") | 
					
						
							|  |  |  | 		if err := a.RunMigrations(); err != nil { | 
					
						
							|  |  |  | 			a.logger.Error("Auto migration failed", zap.Error(err)) | 
					
						
							|  |  |  | 			return fmt.Errorf("auto migration failed: %w", err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		a.logger.Info("Auto migration completed successfully") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-30 19:21:56 +08:00
										 |  |  | 	// 启动容器 | 
					
						
							|  |  |  | 	a.logger.Info("Starting application container...") | 
					
						
							|  |  |  | 	if err := a.container.Start(); err != nil { | 
					
						
							|  |  |  | 		a.logger.Error("Failed to start container", zap.Error(err)) | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-07-28 16:13:59 +08:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	a.logger.Info("Container started successfully, setting up graceful shutdown...") | 
					
						
							| 
									
										
										
										
											2025-06-30 19:21:56 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// 设置优雅关闭 | 
					
						
							|  |  |  | 	a.setupGracefulShutdown() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	a.logger.Info("Application started successfully", | 
					
						
							|  |  |  | 		zap.String("version", a.config.App.Version), | 
					
						
							|  |  |  | 		zap.String("environment", a.config.App.Env), | 
					
						
							|  |  |  | 		zap.String("port", a.config.Server.Port)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// 等待信号 | 
					
						
							|  |  |  | 	return a.waitForShutdown() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // RunMigrations 运行数据库迁移 | 
					
						
							|  |  |  | func (a *Application) RunMigrations() error { | 
					
						
							|  |  |  | 	a.logger.Info("Running database migrations...") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// 创建数据库连接 | 
					
						
							|  |  |  | 	db, err := a.createDatabaseConnection() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return fmt.Errorf("failed to create database connection: %w", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// 自动迁移 | 
					
						
							|  |  |  | 	if err := a.autoMigrate(db); err != nil { | 
					
						
							|  |  |  | 		return fmt.Errorf("failed to run migrations: %w", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	a.logger.Info("Database migrations completed successfully") | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // printBanner 打印启动横幅 | 
					
						
							|  |  |  | func (a *Application) printBanner() { | 
					
						
							|  |  |  | 	banner := fmt.Sprintf(` | 
					
						
							|  |  |  | 	╔══════════════════════════════════════════════════════════════╗ | 
					
						
							| 
									
										
										
										
											2025-07-02 16:17:59 +08:00
										 |  |  | 	║                     %s | 
					
						
							|  |  |  | 	║                     Version: %s | 
					
						
							|  |  |  | 	║                     Environment: %s | 
					
						
							|  |  |  | 	║                     Port: %s | 
					
						
							| 
									
										
										
										
											2025-06-30 19:21:56 +08:00
										 |  |  | 	╚══════════════════════════════════════════════════════════════╝ | 
					
						
							|  |  |  | 	`, | 
					
						
							|  |  |  | 		a.config.App.Name, | 
					
						
							|  |  |  | 		a.config.App.Version, | 
					
						
							|  |  |  | 		a.config.App.Env, | 
					
						
							|  |  |  | 		a.config.Server.Port, | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	fmt.Println(banner) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // setupGracefulShutdown 设置优雅关闭 | 
					
						
							|  |  |  | func (a *Application) setupGracefulShutdown() { | 
					
						
							|  |  |  | 	c := make(chan os.Signal, 1) | 
					
						
							|  |  |  | 	signal.Notify(c, os.Interrupt, syscall.SIGTERM) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	go func() { | 
					
						
							|  |  |  | 		<-c | 
					
						
							|  |  |  | 		a.logger.Info("Received shutdown signal, starting graceful shutdown...") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// 停止容器 | 
					
						
							|  |  |  | 		if err := a.container.Stop(); err != nil { | 
					
						
							|  |  |  | 			a.logger.Error("Error during container shutdown", zap.Error(err)) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		a.logger.Info("Application shutdown completed") | 
					
						
							|  |  |  | 		os.Exit(0) | 
					
						
							|  |  |  | 	}() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // waitForShutdown 等待关闭信号 | 
					
						
							|  |  |  | func (a *Application) waitForShutdown() error { | 
					
						
							|  |  |  | 	// 创建一个通道来等待关闭 | 
					
						
							|  |  |  | 	done := make(chan bool, 1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// 启动一个协程来监听信号 | 
					
						
							|  |  |  | 	go func() { | 
					
						
							|  |  |  | 		c := make(chan os.Signal, 1) | 
					
						
							|  |  |  | 		signal.Notify(c, os.Interrupt, syscall.SIGTERM) | 
					
						
							|  |  |  | 		<-c | 
					
						
							|  |  |  | 		done <- true | 
					
						
							|  |  |  | 	}() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// 等待关闭信号 | 
					
						
							|  |  |  | 	<-done | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // createDatabaseConnection 创建数据库连接 | 
					
						
							|  |  |  | func (a *Application) createDatabaseConnection() (*gorm.DB, error) { | 
					
						
							| 
									
										
										
										
											2025-07-13 16:36:20 +08:00
										 |  |  | 	dbCfg := database.Config{ | 
					
						
							|  |  |  | 		Host:            a.config.Database.Host, | 
					
						
							|  |  |  | 		Port:            a.config.Database.Port, | 
					
						
							|  |  |  | 		User:            a.config.Database.User, | 
					
						
							|  |  |  | 		Password:        a.config.Database.Password, | 
					
						
							|  |  |  | 		Name:            a.config.Database.Name, | 
					
						
							|  |  |  | 		SSLMode:         a.config.Database.SSLMode, | 
					
						
							|  |  |  | 		Timezone:        a.config.Database.Timezone, | 
					
						
							|  |  |  | 		MaxOpenConns:    a.config.Database.MaxOpenConns, | 
					
						
							|  |  |  | 		MaxIdleConns:    a.config.Database.MaxIdleConns, | 
					
						
							|  |  |  | 		ConnMaxLifetime: a.config.Database.ConnMaxLifetime, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	db, err := database.NewConnection(dbCfg) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return db.DB, nil | 
					
						
							| 
									
										
										
										
											2025-06-30 19:21:56 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // autoMigrate 自动迁移 | 
					
						
							|  |  |  | func (a *Application) autoMigrate(db *gorm.DB) error { | 
					
						
							| 
									
										
										
										
											2025-07-11 21:05:58 +08:00
										 |  |  | 	a.logger.Info("Starting database auto migration...") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-02 16:17:59 +08:00
										 |  |  | 	// 如果需要删除某些表,可以在这里手动删除 | 
					
						
							|  |  |  | 	// 注意:这会永久删除数据,请谨慎使用! | 
					
						
							|  |  |  | 	/* | 
					
						
							|  |  |  | 		// 删除不再需要的表(示例,请根据实际情况使用) | 
					
						
							|  |  |  | 		if err := db.Migrator().DropTable(&entities.FavoriteItem{}); err != nil { | 
					
						
							|  |  |  | 			a.logger.Warn("Failed to drop table", zap.Error(err)) | 
					
						
							|  |  |  | 			// 继续执行,不阻断迁移 | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	*/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-11 21:05:58 +08:00
										 |  |  | 	// 自动迁移所有实体 | 
					
						
							| 
									
										
										
										
											2025-06-30 19:21:56 +08:00
										 |  |  | 	return db.AutoMigrate( | 
					
						
							| 
									
										
										
										
											2025-07-11 21:05:58 +08:00
										 |  |  | 		// 用户域 | 
					
						
							| 
									
										
										
										
											2025-06-30 19:21:56 +08:00
										 |  |  | 		&entities.User{}, | 
					
						
							| 
									
										
										
										
											2025-07-02 16:17:59 +08:00
										 |  |  | 		&entities.SMSCode{}, | 
					
						
							| 
									
										
										
										
											2025-07-20 20:53:26 +08:00
										 |  |  | 		&entities.EnterpriseInfo{}, | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  | 		&entities.ContractInfo{}, | 
					
						
							| 
									
										
										
										
											2025-07-11 21:05:58 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// 认证域 | 
					
						
							|  |  |  | 		&certEntities.Certification{}, | 
					
						
							| 
									
										
										
										
											2025-07-20 20:53:26 +08:00
										 |  |  | 		&certEntities.EnterpriseInfoSubmitRecord{}, | 
					
						
							|  |  |  | 		&certEntities.EsignContractGenerateRecord{}, | 
					
						
							|  |  |  | 		&certEntities.EsignContractSignRecord{}, | 
					
						
							| 
									
										
										
										
											2025-07-13 16:36:20 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-11 21:05:58 +08:00
										 |  |  | 		// 财务域 | 
					
						
							|  |  |  | 		&financeEntities.Wallet{}, | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  | 		&financeEntities.WalletTransaction{}, | 
					
						
							|  |  |  | 		&financeEntities.RechargeRecord{}, | 
					
						
							|  |  |  | 		&financeEntities.AlipayOrder{}, | 
					
						
							| 
									
										
										
										
											2025-08-02 02:54:21 +08:00
										 |  |  | 		&financeEntities.InvoiceApplication{}, | 
					
						
							|  |  |  | 		&financeEntities.UserInvoiceInfo{}, | 
					
						
							| 
									
										
										
										
											2025-07-20 20:53:26 +08:00
										 |  |  | 		// 产品域 | 
					
						
							|  |  |  | 		&productEntities.Product{}, | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  | 		&productEntities.ProductPackageItem{}, | 
					
						
							| 
									
										
										
										
											2025-07-20 20:53:26 +08:00
										 |  |  | 		&productEntities.ProductCategory{}, | 
					
						
							|  |  |  | 		&productEntities.Subscription{}, | 
					
						
							|  |  |  | 		&productEntities.ProductDocumentation{}, | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  | 		&productEntities.ProductApiConfig{}, | 
					
						
							|  |  |  | 		// api | 
					
						
							|  |  |  | 		&apiEntities.ApiUser{}, | 
					
						
							|  |  |  | 		&apiEntities.ApiCall{}, | 
					
						
							| 
									
										
										
										
											2025-06-30 19:21:56 +08:00
										 |  |  | 	) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // createLogger 创建日志器 | 
					
						
							|  |  |  | func createLogger(cfg *config.Config) (*zap.Logger, error) { | 
					
						
							|  |  |  | 	level, err := zap.ParseAtomicLevel(cfg.Logger.Level) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		level = zap.NewAtomicLevelAt(zap.InfoLevel) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	config := zap.Config{ | 
					
						
							|  |  |  | 		Level:            level, | 
					
						
							|  |  |  | 		Development:      cfg.App.IsDevelopment(), | 
					
						
							|  |  |  | 		Encoding:         cfg.Logger.Format, | 
					
						
							|  |  |  | 		EncoderConfig:    zap.NewProductionEncoderConfig(), | 
					
						
							|  |  |  | 		OutputPaths:      []string{cfg.Logger.Output}, | 
					
						
							|  |  |  | 		ErrorOutputPaths: []string{"stderr"}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if cfg.Logger.Format == "" { | 
					
						
							|  |  |  | 		config.Encoding = "json" | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if cfg.Logger.Output == "" { | 
					
						
							|  |  |  | 		config.OutputPaths = []string{"stdout"} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return config.Build() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // GetConfig 获取配置 | 
					
						
							|  |  |  | func (a *Application) GetConfig() *config.Config { | 
					
						
							|  |  |  | 	return a.config | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // GetLogger 获取日志器 | 
					
						
							|  |  |  | func (a *Application) GetLogger() *zap.Logger { | 
					
						
							|  |  |  | 	return a.logger | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // HealthCheck 应用程序健康检查 | 
					
						
							|  |  |  | func (a *Application) HealthCheck() error { | 
					
						
							|  |  |  | 	// 这里可以添加应用程序级别的健康检查逻辑 | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // GetVersion 获取版本信息 | 
					
						
							|  |  |  | func (a *Application) GetVersion() map[string]string { | 
					
						
							|  |  |  | 	return map[string]string{ | 
					
						
							|  |  |  | 		"name":        a.config.App.Name, | 
					
						
							|  |  |  | 		"version":     a.config.App.Version, | 
					
						
							|  |  |  | 		"environment": a.config.App.Env, | 
					
						
							|  |  |  | 		"go_version":  "1.23.4+", | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // RunCommand 运行特定命令 | 
					
						
							|  |  |  | func (a *Application) RunCommand(command string, args ...string) error { | 
					
						
							|  |  |  | 	switch command { | 
					
						
							|  |  |  | 	case "migrate": | 
					
						
							|  |  |  | 		return a.RunMigrations() | 
					
						
							|  |  |  | 	case "version": | 
					
						
							|  |  |  | 		version := a.GetVersion() | 
					
						
							|  |  |  | 		fmt.Printf("Name: %s\n", version["name"]) | 
					
						
							|  |  |  | 		fmt.Printf("Version: %s\n", version["version"]) | 
					
						
							|  |  |  | 		fmt.Printf("Environment: %s\n", version["environment"]) | 
					
						
							|  |  |  | 		fmt.Printf("Go Version: %s\n", version["go_version"]) | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	case "health": | 
					
						
							|  |  |  | 		if err := a.HealthCheck(); err != nil { | 
					
						
							|  |  |  | 			fmt.Printf("Health check failed: %v\n", err) | 
					
						
							|  |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		fmt.Println("Application is healthy") | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		return fmt.Errorf("unknown command: %s", command) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } |