Files
goalfylearning-admin/internal/config/config.go
2025-12-05 17:33:13 +08:00

324 lines
9.5 KiB
Go
Raw 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 (
"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"`
UploadMaxSize int64 `mapstructure:"upload_max_size"` // 上传文件最大大小(字节)
AssumeRoleArn string `mapstructure:"assume_role_arn"` // AWS S3专用,阿里云不需要
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 ""
}