| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287 |
- package config
- import (
- "encoding/json"
- "reflect"
- "strconv"
- "strings"
- "sync"
- "github.com/QuantumNous/new-api/common"
- )
- // ConfigManager 统一管理所有配置
- type ConfigManager struct {
- configs map[string]interface{}
- mutex sync.RWMutex
- }
- var GlobalConfig = NewConfigManager()
- func NewConfigManager() *ConfigManager {
- return &ConfigManager{
- configs: make(map[string]interface{}),
- }
- }
- // Register 注册一个配置模块
- func (cm *ConfigManager) Register(name string, config interface{}) {
- cm.mutex.Lock()
- defer cm.mutex.Unlock()
- cm.configs[name] = config
- }
- // Get 获取指定配置模块
- func (cm *ConfigManager) Get(name string) interface{} {
- cm.mutex.RLock()
- defer cm.mutex.RUnlock()
- return cm.configs[name]
- }
- // LoadFromDB 从数据库加载配置
- func (cm *ConfigManager) LoadFromDB(options map[string]string) error {
- cm.mutex.Lock()
- defer cm.mutex.Unlock()
- for name, config := range cm.configs {
- prefix := name + "."
- configMap := make(map[string]string)
- // 收集属于此配置的所有选项
- for key, value := range options {
- if strings.HasPrefix(key, prefix) {
- configKey := strings.TrimPrefix(key, prefix)
- configMap[configKey] = value
- }
- }
- // 如果找到配置项,则更新配置
- if len(configMap) > 0 {
- if err := updateConfigFromMap(config, configMap); err != nil {
- common.SysError("failed to update config " + name + ": " + err.Error())
- continue
- }
- }
- }
- return nil
- }
- // SaveToDB 将配置保存到数据库
- func (cm *ConfigManager) SaveToDB(updateFunc func(key, value string) error) error {
- cm.mutex.RLock()
- defer cm.mutex.RUnlock()
- for name, config := range cm.configs {
- configMap, err := configToMap(config)
- if err != nil {
- return err
- }
- for key, value := range configMap {
- dbKey := name + "." + key
- if err := updateFunc(dbKey, value); err != nil {
- return err
- }
- }
- }
- return nil
- }
- // 辅助函数:将配置对象转换为map
- func configToMap(config interface{}) (map[string]string, error) {
- result := make(map[string]string)
- val := reflect.ValueOf(config)
- if val.Kind() == reflect.Ptr {
- val = val.Elem()
- }
- if val.Kind() != reflect.Struct {
- return nil, nil
- }
- typ := val.Type()
- for i := 0; i < val.NumField(); i++ {
- field := val.Field(i)
- fieldType := typ.Field(i)
- // 跳过未导出字段
- if !fieldType.IsExported() {
- continue
- }
- // 获取json标签作为键名
- key := fieldType.Tag.Get("json")
- if key == "" || key == "-" {
- key = fieldType.Name
- }
- // 处理不同类型的字段
- var strValue string
- switch field.Kind() {
- case reflect.String:
- strValue = field.String()
- case reflect.Bool:
- strValue = strconv.FormatBool(field.Bool())
- case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
- strValue = strconv.FormatInt(field.Int(), 10)
- case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
- strValue = strconv.FormatUint(field.Uint(), 10)
- case reflect.Float32, reflect.Float64:
- strValue = strconv.FormatFloat(field.Float(), 'f', -1, 64)
- case reflect.Ptr:
- // 处理指针类型:如果非 nil,序列化指向的值
- if !field.IsNil() {
- bytes, err := json.Marshal(field.Interface())
- if err != nil {
- return nil, err
- }
- strValue = string(bytes)
- } else {
- // nil 指针序列化为 "null"
- strValue = "null"
- }
- case reflect.Map, reflect.Slice, reflect.Struct:
- // 复杂类型使用JSON序列化
- bytes, err := json.Marshal(field.Interface())
- if err != nil {
- return nil, err
- }
- strValue = string(bytes)
- default:
- // 跳过不支持的类型
- continue
- }
- result[key] = strValue
- }
- return result, nil
- }
- // 辅助函数:从map更新配置对象
- func updateConfigFromMap(config interface{}, configMap map[string]string) error {
- val := reflect.ValueOf(config)
- if val.Kind() != reflect.Ptr {
- return nil
- }
- val = val.Elem()
- if val.Kind() != reflect.Struct {
- return nil
- }
- typ := val.Type()
- for i := 0; i < val.NumField(); i++ {
- field := val.Field(i)
- fieldType := typ.Field(i)
- // 跳过未导出字段
- if !fieldType.IsExported() {
- continue
- }
- // 获取json标签作为键名
- key := fieldType.Tag.Get("json")
- if key == "" || key == "-" {
- key = fieldType.Name
- }
- // 检查map中是否有对应的值
- strValue, ok := configMap[key]
- if !ok {
- continue
- }
- // 根据字段类型设置值
- if !field.CanSet() {
- continue
- }
- switch field.Kind() {
- case reflect.String:
- field.SetString(strValue)
- case reflect.Bool:
- boolValue, err := strconv.ParseBool(strValue)
- if err != nil {
- continue
- }
- field.SetBool(boolValue)
- case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
- intValue, err := strconv.ParseInt(strValue, 10, 64)
- if err != nil {
- continue
- }
- field.SetInt(intValue)
- case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
- uintValue, err := strconv.ParseUint(strValue, 10, 64)
- if err != nil {
- continue
- }
- field.SetUint(uintValue)
- case reflect.Float32, reflect.Float64:
- floatValue, err := strconv.ParseFloat(strValue, 64)
- if err != nil {
- continue
- }
- field.SetFloat(floatValue)
- case reflect.Ptr:
- // 处理指针类型
- if strValue == "null" {
- field.Set(reflect.Zero(field.Type()))
- } else {
- // 如果指针是 nil,需要先初始化
- if field.IsNil() {
- field.Set(reflect.New(field.Type().Elem()))
- }
- // 反序列化到指针指向的值
- err := json.Unmarshal([]byte(strValue), field.Interface())
- if err != nil {
- continue
- }
- }
- case reflect.Map, reflect.Slice, reflect.Struct:
- // 复杂类型使用JSON反序列化
- err := json.Unmarshal([]byte(strValue), field.Addr().Interface())
- if err != nil {
- continue
- }
- }
- }
- return nil
- }
- // ConfigToMap 将配置对象转换为map(导出函数)
- func ConfigToMap(config interface{}) (map[string]string, error) {
- return configToMap(config)
- }
- // UpdateConfigFromMap 从map更新配置对象(导出函数)
- func UpdateConfigFromMap(config interface{}, configMap map[string]string) error {
- return updateConfigFromMap(config, configMap)
- }
- // ExportAllConfigs 导出所有已注册的配置为扁平结构
- func (cm *ConfigManager) ExportAllConfigs() map[string]string {
- cm.mutex.RLock()
- defer cm.mutex.RUnlock()
- result := make(map[string]string)
- for name, cfg := range cm.configs {
- configMap, err := ConfigToMap(cfg)
- if err != nil {
- continue
- }
- // 使用 "模块名.配置项" 的格式添加到结果中
- for key, value := range configMap {
- result[name+"."+key] = value
- }
- }
- return result
- }
|