Files
2025-11-17 13:32:54 +08:00

255 lines
9.1 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package config
import (
"log"
"os"
"strings"
"github.com/spf13/viper"
)
// Config 应用配置结构
type Config struct {
Server ServerConfig `mapstructure:"server"`
Database DatabaseConfig `mapstructure:"database"`
Redis RedisConfig `mapstructure:"redis"`
JWT JWTConfig `mapstructure:"jwt"`
Log LogConfig `mapstructure:"log"`
WeChat WeChatConfig `mapstructure:"wechat"`
WeChatPay WeChatPayConfig `mapstructure:"wechatPay"`
Upload UploadConfig `mapstructure:"upload"`
}
// ServerConfig 服务器配置
type ServerConfig struct {
Port int `mapstructure:"port"`
Mode string `mapstructure:"mode"`
}
// DatabaseConfig 数据库配置
type DatabaseConfig struct {
Driver string `mapstructure:"driver"`
Host string `mapstructure:"host"`
Port int `mapstructure:"port"`
Username string `mapstructure:"username"`
Password string `mapstructure:"password"`
DBName string `mapstructure:"dbname"`
Charset string `mapstructure:"charset"`
ParseTime bool `mapstructure:"parseTime"`
Loc string `mapstructure:"loc"`
AutoMigrate bool `mapstructure:"autoMigrate"` // 是否自动迁移数据库表
LogLevel string `mapstructure:"logLevel"` // GORM日志级别silent, error, warn, info
}
// RedisConfig Redis配置
type RedisConfig struct {
Host string `mapstructure:"host"`
Port int `mapstructure:"port"`
Password string `mapstructure:"password"`
DB int `mapstructure:"db"`
}
// JWTConfig JWT配置
type JWTConfig struct {
Secret string `mapstructure:"secret"`
Expire int `mapstructure:"expire"`
}
// LogConfig 日志配置
type LogConfig struct {
Level string `mapstructure:"level"`
Filename string `mapstructure:"filename"`
MaxSize int `mapstructure:"maxSize"`
MaxAge int `mapstructure:"maxAge"`
MaxBackups int `mapstructure:"maxBackups"`
EnableConsole bool `mapstructure:"enableConsole"` // 是否启用控制台输出
EnableFile bool `mapstructure:"enableFile"` // 是否启用文件输出
Format string `mapstructure:"format"` // 日志格式json 或 text
EnableCaller bool `mapstructure:"enableCaller"` // 是否显示调用者信息
EnableOperation bool `mapstructure:"enableOperation"` // 是否启用操作日志
EnablePerf bool `mapstructure:"enablePerf"` // 是否启用性能日志
PerfThreshold int64 `mapstructure:"perfThreshold"` // 性能日志阈值(毫秒)
}
// WeChatConfig 微信配置
type WeChatConfig struct {
AppID string `mapstructure:"appId"`
AppSecret string `mapstructure:"appSecret"`
}
// WeChatPayConfig 微信支付配置
type WeChatPayConfig struct {
AppID string `mapstructure:"appId"` // 小程序APPID
MchID string `mapstructure:"mchId"` // 商户号
APIv3Key string `mapstructure:"apiV3Key"` // APIv3密钥
CertPath string `mapstructure:"certPath"` // 商户证书路径
KeyPath string `mapstructure:"keyPath"` // 商户私钥路径
SerialNo string `mapstructure:"serialNo"` // 证书序列号
NotifyURL string `mapstructure:"notifyUrl"` // 支付回调地址
RefundNotifyURL string `mapstructure:"refundNotifyUrl"` // 退款回调地址
Environment string `mapstructure:"environment"` // 环境sandbox 或 production
}
// UploadConfig 文件上传配置
type UploadConfig struct {
MaxImageSize int64 `mapstructure:"maxImageSize"` // 图片最大大小(字节)
MaxFileSize int64 `mapstructure:"maxFileSize"` // 文件最大大小(字节)
ImageTypes []string `mapstructure:"imageTypes"` // 允许的图片类型
StaticPath string `mapstructure:"staticPath"` // 静态文件路径(本地存储)
BaseURL string `mapstructure:"baseUrl"` // 静态文件访问基础URL本地存储
StorageType string `mapstructure:"storageType"` // 存储类型local(本地) 或 oss(阿里云OSS)
OSS OSSConfig `mapstructure:"oss"` // OSS配置
}
// OSSConfig 阿里云OSS配置
type OSSConfig struct {
Endpoint string `mapstructure:"endpoint"` // OSS访问域名
AccessKeyID string `mapstructure:"accessKeyId"` // AccessKey ID
AccessKeySecret string `mapstructure:"accessKeySecret"` // AccessKey Secret
BucketName string `mapstructure:"bucketName"` // Bucket名称
BasePath string `mapstructure:"basePath"` // 文件存储基础路径
Domain string `mapstructure:"domain"` // 自定义域名(可选)
}
// Load 加载配置
func Load() *Config {
// 获取环境变量默认为development
env := getEnvironment()
// 根据环境选择配置文件
configName := getConfigName(env)
viper.SetConfigName(configName)
viper.SetConfigType("yaml")
viper.AddConfigPath("./configs")
viper.AddConfigPath("../configs")
viper.AddConfigPath("../../configs")
// 设置默认值
setDefaults()
// 启用环境变量支持
viper.AutomaticEnv()
viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
if err := viper.ReadInConfig(); err != nil {
log.Printf("配置文件读取失败: %v, 使用默认配置", err)
} else {
log.Printf("成功加载配置文件: %s (环境: %s)", viper.ConfigFileUsed(), env)
}
var config Config
if err := viper.Unmarshal(&config); err != nil {
log.Fatalf("配置解析失败: %v", err)
}
// 显示配置信息
logConfigInfo(&config, env)
return &config
}
// logConfigInfo 记录配置信息
func logConfigInfo(config *Config, env string) {
log.Printf("=== 配置信息 ===")
log.Printf("环境: %s", env)
log.Printf("服务器端口: %d", config.Server.Port)
log.Printf("服务器模式: %s", config.Server.Mode)
log.Printf("数据库: %s@%s:%d/%s", config.Database.Username, config.Database.Host, config.Database.Port, config.Database.DBName)
log.Printf("数据库自动迁移: %t", config.Database.AutoMigrate)
log.Printf("Redis: %s:%d (DB:%d)", config.Redis.Host, config.Redis.Port, config.Redis.DB)
log.Printf("日志级别: %s", config.Log.Level)
log.Printf("微信AppID: %s", config.WeChat.AppID)
log.Printf("===============")
}
// getEnvironment 获取当前环境
func getEnvironment() string {
env := os.Getenv("GO_ENV")
if env == "" {
env = os.Getenv("APP_ENV")
}
if env == "" {
env = os.Getenv("ENVIRONMENT")
}
if env == "" {
env = "development" // 默认环境
}
return strings.ToLower(env)
}
// getConfigName 根据环境获取配置文件名
func getConfigName(env string) string {
switch env {
case "development", "dev":
return "config.dev"
case "test", "testing":
return "config.test"
case "production", "prod":
return "config.prod"
default:
// 如果环境不匹配,尝试使用默认配置文件
if _, err := os.Stat("./configs/config.yaml"); err == nil {
return "config"
}
// 如果默认配置文件不存在,使用开发环境配置
log.Printf("未知环境 '%s',使用开发环境配置", env)
return "config.dev"
}
}
// setDefaults 设置默认配置
func setDefaults() {
// 服务器默认配置
viper.SetDefault("server.port", 8080)
viper.SetDefault("server.mode", "debug")
// 数据库默认配置
viper.SetDefault("database.driver", "mysql")
viper.SetDefault("database.host", "localhost")
viper.SetDefault("database.port", 3306)
viper.SetDefault("database.username", "root")
viper.SetDefault("database.password", "")
viper.SetDefault("database.dbname", "dianshang")
viper.SetDefault("database.charset", "utf8mb4")
viper.SetDefault("database.parseTime", true)
viper.SetDefault("database.loc", "Local")
viper.SetDefault("database.autoMigrate", true) // 默认启用自动迁移
viper.SetDefault("database.logLevel", "warn") // 默认warn级别
// Redis默认配置
viper.SetDefault("redis.host", "localhost")
viper.SetDefault("redis.port", 6379)
viper.SetDefault("redis.password", "")
viper.SetDefault("redis.db", 0)
// JWT默认配置
viper.SetDefault("jwt.secret", "your-secret-key")
viper.SetDefault("jwt.expire", 7200)
// 日志默认配置
viper.SetDefault("log.level", "info")
viper.SetDefault("log.filename", "logs/app.log")
viper.SetDefault("log.maxSize", 100)
viper.SetDefault("log.maxAge", 30)
viper.SetDefault("log.maxBackups", 5)
viper.SetDefault("log.enableConsole", true)
viper.SetDefault("log.enableFile", true)
// 文件上传默认配置
viper.SetDefault("upload.maxImageSize", 5*1024*1024) // 5MB
viper.SetDefault("upload.maxFileSize", 10*1024*1024) // 10MB
viper.SetDefault("upload.imageTypes", []string{".jpg", ".jpeg", ".png", ".gif", ".webp", ".svg"})
viper.SetDefault("upload.staticPath", "./static")
viper.SetDefault("upload.baseUrl", "http://localhost:8080")
viper.SetDefault("upload.storageType", "local") // 默认使用本地存储
viper.SetDefault("log.format", "json")
viper.SetDefault("log.enableCaller", true)
viper.SetDefault("log.enableOperation", true)
viper.SetDefault("log.enablePerf", true)
viper.SetDefault("log.perfThreshold", 1000) // 1秒
// 微信默认配置
viper.SetDefault("wechat.appId", "wx430b70d696b4dbd7")
viper.SetDefault("wechat.appSecret", "your-wechat-app-secret")
}