Spaces:
Build error
Build error
| package config | |
| import ( | |
| "encoding/json" | |
| "one-api/common" | |
| "reflect" | |
| "strconv" | |
| "strings" | |
| "sync" | |
| ) | |
| // 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.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.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 | |
| } | |