package config import ( "fmt" "os" "github.com/spf13/viper" ) type Config struct { Server ServerConfig Database DatabaseConfig Redis RedisConfig JWT JWTConfig Captcha CaptchaConfig } type ServerConfig struct { Host string Port int Mode string } type DatabaseConfig struct { Type string // sqlite or mysql Host string Port int User string Password string Database string SQLite SQLiteConfig } type SQLiteConfig struct { Path string } type RedisConfig struct { Enabled bool Host string Port int Password string DB int } type JWTConfig struct { Secret string ExpireTime int // hours } type CaptchaConfig struct { ModelPath string } var Cfg *Config func Load(configPath string) error { viper.SetConfigName("config") viper.SetConfigType("yaml") viper.AddConfigPath(".") viper.AddConfigPath("./data") viper.AddConfigPath(configPath) // 默认值 viper.SetDefault("server.host", "0.0.0.0") viper.SetDefault("server.port", 6688) viper.SetDefault("server.mode", "release") viper.SetDefault("database.type", "sqlite") viper.SetDefault("database.sqlite.path", "./data/app.db") viper.SetDefault("database.host", "localhost") viper.SetDefault("database.port", 3306) viper.SetDefault("redis.enabled", false) viper.SetDefault("redis.host", "localhost") viper.SetDefault("redis.port", 6379) viper.SetDefault("redis.db", 0) viper.SetDefault("jwt.expire_time", 1440) // 60 days viper.SetDefault("captcha.model_path", "./models") if err := viper.ReadInConfig(); err != nil { if _, ok := err.(viper.ConfigFileNotFoundError); ok { return fmt.Errorf("配置文件未找到,请先运行安装向导") } return err } Cfg = &Config{} if err := viper.Unmarshal(Cfg); err != nil { return err } // 从环境变量读取 JWT Secret if secret := os.Getenv("JWT_SECRET"); secret != "" { Cfg.JWT.Secret = secret } return nil } func Save(cfg *Config) error { viper.Set("server", cfg.Server) viper.Set("database", cfg.Database) viper.Set("redis", cfg.Redis) viper.Set("jwt", cfg.JWT) viper.Set("captcha", cfg.Captcha) return viper.WriteConfig() } func IsInstalled() bool { _, err := os.Stat("./data/config.yaml") return err == nil }