package config import ( "fmt" "os" "time" "github.com/spf13/viper" ) type Config struct { App AppConfig `mapstructure:"app"` Server ServerConfig `mapstructure:"server"` Security SecurityConfig `mapstructure:"security"` SMS SMSConfig `mapstructure:"sms"` Database DatabaseConfig `mapstructure:"database"` Timezone string `mapstructure:"timezone"` APITokens []APIToken `mapstructure:"api_tokens"` } type AppConfig struct { Name string `mapstructure:"name"` Version string `mapstructure:"version"` } type ServerConfig struct { Host string `mapstructure:"host"` Port int `mapstructure:"port"` Debug bool `mapstructure:"debug"` } type SecurityConfig struct { Enabled bool `mapstructure:"enabled"` Username string `mapstructure:"username"` Password string `mapstructure:"password"` SessionLifetime int `mapstructure:"session_lifetime"` SecretKey string `mapstructure:"secret_key"` SignVerify bool `mapstructure:"sign_verify"` SignMaxAge int64 `mapstructure:"sign_max_age"` } type SMSConfig struct { MaxMessages int `mapstructure:"max_messages"` AutoCleanup bool `mapstructure:"auto_cleanup"` CleanupDays int `mapstructure:"cleanup_days"` } type DatabaseConfig struct { Path string `mapstructure:"path"` } type APIToken struct { Name string `mapstructure:"name"` Token string `mapstructure:"token"` Secret string `mapstructure:"secret"` Enabled bool `mapstructure:"enabled"` } var cfg *Config func Load(configPath string) (*Config, error) { viper.SetConfigFile(configPath) viper.SetConfigType("yaml") // 允许环境变量覆盖 viper.AutomaticEnv() if err := viper.ReadInConfig(); err != nil { return nil, fmt.Errorf("读取配置文件失败: %w", err) } cfg = &Config{} if err := viper.Unmarshal(cfg); err != nil { return nil, fmt.Errorf("解析配置文件失败: %w", err) } return cfg, nil } func Get() *Config { return cfg } // GetSessionLifetimeDuration 返回会话 lifetime 为 duration func (c *Config) GetSessionLifetimeDuration() time.Duration { return time.Duration(c.Security.SessionLifetime) * time.Second } // GetSignMaxAgeDuration 返回签名最大有效期 func (c *Config) GetSignMaxAgeDuration() time.Duration { return time.Duration(c.Security.SignMaxAge) * time.Millisecond } // GetServerAddress 返回服务器地址 func (c *Config) GetServerAddress() string { return fmt.Sprintf("%s:%d", c.Server.Host, c.Server.Port) } // GetTokenByName 根据名称获取 Token 配置 func (c *Config) GetTokenByName(name string) *APIToken { for i := range c.APITokens { if c.APITokens[i].Name == name && c.APITokens[i].Enabled { return &c.APITokens[i] } } return nil } // GetTokenByValue 根据 token 值获取配置 func (c *Config) GetTokenByValue(token string) *APIToken { for i := range c.APITokens { if c.APITokens[i].Token == token && c.APITokens[i].Enabled { return &c.APITokens[i] } } return nil } // Save 保存配置到文件 func (c *Config) Save(path string) error { viper.Set("app", c.App) viper.Set("server", c.Server) viper.Set("security", c.Security) viper.Set("sms", c.SMS) viper.Set("database", c.Database) viper.Set("timezone", c.Timezone) viper.Set("api_tokens", c.APITokens) return viper.WriteConfigAs(path) } // LoadDefault 加载默认配置文件 func LoadDefault() (*Config, error) { configPath := "config.yaml" if _, err := os.Stat(configPath); os.IsNotExist(err) { // 尝试查找上层目录 if _, err := os.Stat("../config.yaml"); err == nil { configPath = "../config.yaml" } } return Load(configPath) }