feat():learning后台管理项目初始化
This commit is contained in:
47
internal/config/README.md
Normal file
47
internal/config/README.md
Normal file
@@ -0,0 +1,47 @@
|
||||
# 配置管理
|
||||
|
||||
本模块负责管理应用程序的配置,支持从 YAML 文件加载配置。
|
||||
|
||||
## 功能特性
|
||||
|
||||
- 支持 YAML 配置文件
|
||||
- 配置热加载
|
||||
- 默认值设置
|
||||
- 类型安全的配置结构
|
||||
|
||||
## 配置结构
|
||||
|
||||
```yaml
|
||||
server:
|
||||
addr: "0.0.0.0"
|
||||
port: 8080
|
||||
|
||||
database:
|
||||
dsn: "user:password@tcp(localhost:3306)/goalfymax_admin?charset=utf8mb4&parseTime=True&loc=Local"
|
||||
maxIdleConns: 10
|
||||
maxOpenConns: 100
|
||||
|
||||
admin:
|
||||
loginKey: "your-admin-password"
|
||||
jwtSecret: "your-jwt-secret"
|
||||
|
||||
log:
|
||||
level: "info"
|
||||
format: "json"
|
||||
output: "stdout"
|
||||
```
|
||||
|
||||
## 使用方法
|
||||
|
||||
```go
|
||||
// 加载配置
|
||||
err := config.LoadConfig("etc/config.yaml")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// 获取配置
|
||||
cfg := config.GetConfig()
|
||||
fmt.Println(cfg.Server.Addr)
|
||||
```
|
||||
|
||||
322
internal/config/config.go
Normal file
322
internal/config/config.go
Normal file
@@ -0,0 +1,322 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/viper"
|
||||
"gorm.io/driver/mysql"
|
||||
)
|
||||
|
||||
// DatabaseConfig 数据库配置
|
||||
type DatabaseConfig struct {
|
||||
DSN string `mapstructure:"dsn"`
|
||||
MaxIdleConns int `mapstructure:"maxIdleConns"`
|
||||
MaxOpenConns int `mapstructure:"maxOpenConns"`
|
||||
LogLevel string `mapstructure:"logLevel"`
|
||||
}
|
||||
|
||||
// ServerConfig 服务器配置
|
||||
type ServerConfig struct {
|
||||
Addr string `mapstructure:"addr"`
|
||||
Port int `mapstructure:"port"`
|
||||
}
|
||||
|
||||
// GatewayConfig 网关配置
|
||||
type GatewayConfig struct {
|
||||
BaseURL string `mapstructure:"base_url"`
|
||||
Timeout int `mapstructure:"timeout"`
|
||||
Auth GatewayAuthConfig `mapstructure:"auth"`
|
||||
}
|
||||
|
||||
// GatewayAuthConfig 网关鉴权配置
|
||||
type GatewayAuthConfig struct {
|
||||
LoginURL string `mapstructure:"login_url"`
|
||||
Key string `mapstructure:"key"`
|
||||
}
|
||||
|
||||
// SSOConfig SSO配置
|
||||
type SSOConfig struct {
|
||||
SSOServerURL string `mapstructure:"sso_server_url"`
|
||||
ClientID string `mapstructure:"client_id"`
|
||||
ClientSecret string `mapstructure:"client_secret"`
|
||||
RedirectURI string `mapstructure:"redirect_uri"`
|
||||
Scope string `mapstructure:"scope"`
|
||||
ResourceAud string `mapstructure:"resource_aud"`
|
||||
AdminToken string `mapstructure:"admin_token"`
|
||||
Timeout time.Duration `mapstructure:"timeout"`
|
||||
}
|
||||
|
||||
// MessagePushConfig 消息推送配置
|
||||
type MessagePushConfig struct {
|
||||
GoalfyMaxBaseURL string `mapstructure:"goalfymax_base_url"`
|
||||
Timeout int `mapstructure:"timeout"`
|
||||
RetryCount int `mapstructure:"retry_count"`
|
||||
RetryInterval int `mapstructure:"retry_interval"`
|
||||
}
|
||||
|
||||
// AlertConfig 告警配置
|
||||
type AlertConfig struct {
|
||||
DingTalk DingTalkConfig `mapstructure:"dingtalk"`
|
||||
}
|
||||
|
||||
// DingTalkConfig 钉钉配置
|
||||
type DingTalkConfig struct {
|
||||
Enabled bool `mapstructure:"enabled"`
|
||||
Webhook string `mapstructure:"webhook"`
|
||||
Secret string `mapstructure:"secret"`
|
||||
TimeoutSeconds int `mapstructure:"timeout_seconds"`
|
||||
Keyword string `mapstructure:"keyword"`
|
||||
}
|
||||
|
||||
// PayConfig 支付服务配置
|
||||
type PayConfig struct {
|
||||
BaseURL string `mapstructure:"base_url"`
|
||||
Timeout int `mapstructure:"timeout"`
|
||||
}
|
||||
|
||||
// OssConfig 对象存储(S3兼容)配置
|
||||
type OssConfig struct {
|
||||
Endpoint string `mapstructure:"endpoint"`
|
||||
Region string `mapstructure:"region"`
|
||||
AccessKeyID string `mapstructure:"access_key_id"`
|
||||
AccessKeySecret string `mapstructure:"access_key_secret"`
|
||||
Bucket string `mapstructure:"bucket"`
|
||||
AssumeRoleArn string `mapstructure:"assume_role_arn"`
|
||||
PresignUrlExpire time.Duration `mapstructure:"presign_url_expire"`
|
||||
}
|
||||
|
||||
// RedisConfig Redis配置
|
||||
type RedisConfig struct {
|
||||
Addr string `mapstructure:"addr"`
|
||||
Password string `mapstructure:"password"`
|
||||
DB int `mapstructure:"db"`
|
||||
}
|
||||
|
||||
// EmailConfig 邮件配置
|
||||
type EmailConfig struct {
|
||||
Sender string `mapstructure:"sender"`
|
||||
Host string `mapstructure:"host"`
|
||||
Port int `mapstructure:"port"`
|
||||
Username string `mapstructure:"username"`
|
||||
Password string `mapstructure:"password"`
|
||||
InviteURLPrefix string `mapstructure:"invite_url_prefix"`
|
||||
}
|
||||
|
||||
// Config 定义总配置结构
|
||||
type Config struct {
|
||||
Server ServerConfig `mapstructure:"server"`
|
||||
Database DatabaseConfig `mapstructure:"database"`
|
||||
Gateway GatewayConfig `mapstructure:"gateway"`
|
||||
SSO SSOConfig `mapstructure:"sso"`
|
||||
MessagePush MessagePushConfig `mapstructure:"message_push"`
|
||||
Alert AlertConfig `mapstructure:"alert"`
|
||||
Oss OssConfig `mapstructure:"oss"`
|
||||
Redis RedisConfig `mapstructure:"redis"`
|
||||
Email EmailConfig `mapstructure:"email"`
|
||||
Log LogConfig `mapstructure:"log"`
|
||||
Client ClientConfig `mapstructure:"client"`
|
||||
PostgreSQL PostgreSQLConfig `mapstructure:"postgresql"`
|
||||
Pay PayConfig `mapstructure:"pay"`
|
||||
Jobs JobsConfig `mapstructure:"jobs"`
|
||||
}
|
||||
|
||||
// LogConfig 日志配置
|
||||
type LogConfig struct {
|
||||
Level string `mapstructure:"level"`
|
||||
Format string `mapstructure:"format"`
|
||||
Output string `mapstructure:"output"`
|
||||
}
|
||||
|
||||
// ClientOption 客户端选项
|
||||
type ClientOption struct {
|
||||
Key string `mapstructure:"key" json:"key"`
|
||||
Value string `mapstructure:"value" json:"value"`
|
||||
Label string `json:"label"` // 用于前端展示,格式:key+value
|
||||
}
|
||||
|
||||
// ClientConfig 客户端配置
|
||||
type ClientConfig struct {
|
||||
Options []ClientOption `mapstructure:"options"`
|
||||
}
|
||||
|
||||
// PostgreSQLConfig PG配置
|
||||
type PostgreSQLConfig struct {
|
||||
DSN string `mapstructure:"dsn"`
|
||||
Host string `mapstructure:"host"`
|
||||
Port int `mapstructure:"port"`
|
||||
User string `mapstructure:"user"`
|
||||
Password string `mapstructure:"password"`
|
||||
DBName string `mapstructure:"dbname"`
|
||||
SSLMode string `mapstructure:"sslmode"`
|
||||
MaxOpenConns int `mapstructure:"max_open_conns"`
|
||||
MaxIdleConns int `mapstructure:"max_idle_conns"`
|
||||
ConnMaxLifetime time.Duration `mapstructure:"conn_max_lifetime"`
|
||||
ConnMaxIdleTime time.Duration `mapstructure:"conn_max_idle_time"`
|
||||
}
|
||||
|
||||
type JobsConfig struct {
|
||||
McpUsageBalance McpUsageBalanceJobConfig `mapstructure:"mcp_usage_balance"`
|
||||
ModelTokenBalance ModelTokenBalanceJobConfig `mapstructure:"model_token_balance"`
|
||||
}
|
||||
|
||||
type McpUsageBalanceJobConfig struct {
|
||||
Enabled bool `mapstructure:"enabled"`
|
||||
RunOnStartup bool `mapstructure:"run_on_startup"`
|
||||
DelayMinutes int `mapstructure:"delay_minutes"`
|
||||
}
|
||||
|
||||
type ModelTokenBalanceJobConfig struct {
|
||||
Enabled bool `mapstructure:"enabled"`
|
||||
RunOnStartup bool `mapstructure:"run_on_startup"`
|
||||
DelayMinutes int `mapstructure:"delay_minutes"`
|
||||
}
|
||||
|
||||
func (j JobsConfig) IsMcpUsageEnabled() bool {
|
||||
return j.McpUsageBalance.Enabled
|
||||
}
|
||||
|
||||
var (
|
||||
config *Config
|
||||
configLock sync.RWMutex
|
||||
)
|
||||
|
||||
// LoadConfig 从文件加载配置
|
||||
func LoadConfig(path string) error {
|
||||
fmt.Printf("Loading config from %s\n", path)
|
||||
viper.SetConfigFile(path)
|
||||
err := viper.ReadInConfig()
|
||||
if err != nil {
|
||||
return fmt.Errorf("读取配置文件失败: %w", err)
|
||||
}
|
||||
|
||||
if err := viper.Unmarshal(&config); err != nil {
|
||||
return fmt.Errorf("解析配置文件失败: %w", err)
|
||||
}
|
||||
|
||||
// 设置默认值
|
||||
if config.Server.Addr == "" {
|
||||
config.Server.Addr = "0.0.0.0"
|
||||
}
|
||||
if config.Server.Port == 0 {
|
||||
config.Server.Port = 8080
|
||||
}
|
||||
if config.Database.MaxIdleConns == 0 {
|
||||
config.Database.MaxIdleConns = 10
|
||||
}
|
||||
if config.Database.MaxOpenConns == 0 {
|
||||
config.Database.MaxOpenConns = 100
|
||||
}
|
||||
if config.Database.LogLevel == "" {
|
||||
config.Database.LogLevel = "info"
|
||||
}
|
||||
if config.Log.Level == "" {
|
||||
config.Log.Level = "info"
|
||||
}
|
||||
if config.Log.Format == "" {
|
||||
config.Log.Format = "json"
|
||||
}
|
||||
if config.Log.Output == "" {
|
||||
config.Log.Output = "stdout"
|
||||
}
|
||||
if config.Jobs.McpUsageBalance.DelayMinutes <= 0 {
|
||||
config.Jobs.McpUsageBalance.DelayMinutes = 5
|
||||
}
|
||||
if config.Jobs.ModelTokenBalance.DelayMinutes <= 0 {
|
||||
config.Jobs.ModelTokenBalance.DelayMinutes = 5
|
||||
}
|
||||
if config.Gateway.BaseURL == "" {
|
||||
config.Gateway.BaseURL = "http://localhost:8080"
|
||||
}
|
||||
if config.Gateway.Timeout == 0 {
|
||||
config.Gateway.Timeout = 30
|
||||
}
|
||||
if config.Gateway.Auth.LoginURL == "" {
|
||||
config.Gateway.Auth.LoginURL = "http://44.247.156.94:8080/aigateway-admin/api/login"
|
||||
}
|
||||
if config.Gateway.Auth.Key == "" {
|
||||
config.Gateway.Auth.Key = "Jiahe.123"
|
||||
}
|
||||
if config.MessagePush.GoalfyMaxBaseURL == "" {
|
||||
config.MessagePush.GoalfyMaxBaseURL = "http://goalfymax-backend:8080"
|
||||
}
|
||||
if config.MessagePush.Timeout == 0 {
|
||||
config.MessagePush.Timeout = 30
|
||||
}
|
||||
if config.MessagePush.RetryCount == 0 {
|
||||
config.MessagePush.RetryCount = 3
|
||||
}
|
||||
if config.MessagePush.RetryInterval == 0 {
|
||||
config.MessagePush.RetryInterval = 1000
|
||||
}
|
||||
if config.Pay.BaseURL == "" {
|
||||
config.Pay.BaseURL = "http://goalfy-pay:8080"
|
||||
}
|
||||
if config.Pay.Timeout == 0 {
|
||||
config.Pay.Timeout = 30
|
||||
}
|
||||
if config.Redis.Addr == "" {
|
||||
config.Redis.Addr = "localhost:6379"
|
||||
}
|
||||
if config.Redis.DB == 0 {
|
||||
config.Redis.DB = 0
|
||||
}
|
||||
|
||||
// OSS 预签名默认过期时间
|
||||
if config.Oss.PresignUrlExpire == 0 {
|
||||
config.Oss.PresignUrlExpire = 10 * time.Minute
|
||||
}
|
||||
|
||||
if config.Alert.DingTalk.TimeoutSeconds <= 0 {
|
||||
config.Alert.DingTalk.TimeoutSeconds = 5
|
||||
}
|
||||
|
||||
// 设置客户端默认选项
|
||||
if len(config.Client.Options) == 0 {
|
||||
config.Client.Options = []ClientOption{
|
||||
{Key: "5hNXkkkVPfFWUjRvzVP23w", Value: "https://ob-staging-goalfymax.goalfyai.com/"},
|
||||
{Key: "J10f8yxU1XDl1Tn00MXKeA", Value: "https://staging-goalfymax.goalfyai.com/"},
|
||||
{Key: "xRpT9mgNpt2YvoY9z4FToA", Value: "https://goalfymax.goalfyai.com/"},
|
||||
}
|
||||
}
|
||||
|
||||
// 为每个客户端选项生成 label
|
||||
for i := range config.Client.Options {
|
||||
config.Client.Options[i].Label = config.Client.Options[i].Key + "+" + config.Client.Options[i].Value
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetConfig 获取当前配置
|
||||
func GetConfig() *Config {
|
||||
configLock.RLock()
|
||||
defer configLock.RUnlock()
|
||||
return config
|
||||
}
|
||||
|
||||
// GetDatabaseConfig 获取数据库配置
|
||||
func GetDatabaseConfig() mysql.Config {
|
||||
cfg := GetConfig()
|
||||
return mysql.Config{
|
||||
DSN: cfg.Database.DSN,
|
||||
}
|
||||
}
|
||||
|
||||
// GetClientOptions 获取客户端选项列表
|
||||
func GetClientOptions() []ClientOption {
|
||||
cfg := GetConfig()
|
||||
return cfg.Client.Options
|
||||
}
|
||||
|
||||
// GetClientValue 根据key获取客户端的展示值
|
||||
func GetClientValue(key string) string {
|
||||
options := GetClientOptions()
|
||||
for _, opt := range options {
|
||||
if opt.Key == key {
|
||||
return opt.Value
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
Reference in New Issue
Block a user