config.go 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. package config
  2. import (
  3. "encoding/json"
  4. "one-api/common"
  5. "reflect"
  6. "strconv"
  7. "strings"
  8. "sync"
  9. )
  10. // ConfigManager 统一管理所有配置
  11. type ConfigManager struct {
  12. configs map[string]interface{}
  13. mutex sync.RWMutex
  14. }
  15. var GlobalConfig = NewConfigManager()
  16. func NewConfigManager() *ConfigManager {
  17. return &ConfigManager{
  18. configs: make(map[string]interface{}),
  19. }
  20. }
  21. // Register 注册一个配置模块
  22. func (cm *ConfigManager) Register(name string, config interface{}) {
  23. cm.mutex.Lock()
  24. defer cm.mutex.Unlock()
  25. cm.configs[name] = config
  26. }
  27. // Get 获取指定配置模块
  28. func (cm *ConfigManager) Get(name string) interface{} {
  29. cm.mutex.RLock()
  30. defer cm.mutex.RUnlock()
  31. return cm.configs[name]
  32. }
  33. // LoadFromDB 从数据库加载配置
  34. func (cm *ConfigManager) LoadFromDB(options map[string]string) error {
  35. cm.mutex.Lock()
  36. defer cm.mutex.Unlock()
  37. for name, config := range cm.configs {
  38. prefix := name + "."
  39. configMap := make(map[string]string)
  40. // 收集属于此配置的所有选项
  41. for key, value := range options {
  42. if strings.HasPrefix(key, prefix) {
  43. configKey := strings.TrimPrefix(key, prefix)
  44. configMap[configKey] = value
  45. }
  46. }
  47. // 如果找到配置项,则更新配置
  48. if len(configMap) > 0 {
  49. if err := updateConfigFromMap(config, configMap); err != nil {
  50. common.SysError("failed to update config " + name + ": " + err.Error())
  51. continue
  52. }
  53. }
  54. }
  55. return nil
  56. }
  57. // SaveToDB 将配置保存到数据库
  58. func (cm *ConfigManager) SaveToDB(updateFunc func(key, value string) error) error {
  59. cm.mutex.RLock()
  60. defer cm.mutex.RUnlock()
  61. for name, config := range cm.configs {
  62. configMap, err := configToMap(config)
  63. if err != nil {
  64. return err
  65. }
  66. for key, value := range configMap {
  67. dbKey := name + "." + key
  68. if err := updateFunc(dbKey, value); err != nil {
  69. return err
  70. }
  71. }
  72. }
  73. return nil
  74. }
  75. // 辅助函数:将配置对象转换为map
  76. func configToMap(config interface{}) (map[string]string, error) {
  77. result := make(map[string]string)
  78. val := reflect.ValueOf(config)
  79. if val.Kind() == reflect.Ptr {
  80. val = val.Elem()
  81. }
  82. if val.Kind() != reflect.Struct {
  83. return nil, nil
  84. }
  85. typ := val.Type()
  86. for i := 0; i < val.NumField(); i++ {
  87. field := val.Field(i)
  88. fieldType := typ.Field(i)
  89. // 跳过未导出字段
  90. if !fieldType.IsExported() {
  91. continue
  92. }
  93. // 获取json标签作为键名
  94. key := fieldType.Tag.Get("json")
  95. if key == "" || key == "-" {
  96. key = fieldType.Name
  97. }
  98. // 处理不同类型的字段
  99. var strValue string
  100. switch field.Kind() {
  101. case reflect.String:
  102. strValue = field.String()
  103. case reflect.Bool:
  104. strValue = strconv.FormatBool(field.Bool())
  105. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  106. strValue = strconv.FormatInt(field.Int(), 10)
  107. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
  108. strValue = strconv.FormatUint(field.Uint(), 10)
  109. case reflect.Float32, reflect.Float64:
  110. strValue = strconv.FormatFloat(field.Float(), 'f', -1, 64)
  111. case reflect.Map, reflect.Slice, reflect.Struct:
  112. // 复杂类型使用JSON序列化
  113. bytes, err := json.Marshal(field.Interface())
  114. if err != nil {
  115. return nil, err
  116. }
  117. strValue = string(bytes)
  118. default:
  119. // 跳过不支持的类型
  120. continue
  121. }
  122. result[key] = strValue
  123. }
  124. return result, nil
  125. }
  126. // 辅助函数:从map更新配置对象
  127. func updateConfigFromMap(config interface{}, configMap map[string]string) error {
  128. val := reflect.ValueOf(config)
  129. if val.Kind() != reflect.Ptr {
  130. return nil
  131. }
  132. val = val.Elem()
  133. if val.Kind() != reflect.Struct {
  134. return nil
  135. }
  136. typ := val.Type()
  137. for i := 0; i < val.NumField(); i++ {
  138. field := val.Field(i)
  139. fieldType := typ.Field(i)
  140. // 跳过未导出字段
  141. if !fieldType.IsExported() {
  142. continue
  143. }
  144. // 获取json标签作为键名
  145. key := fieldType.Tag.Get("json")
  146. if key == "" || key == "-" {
  147. key = fieldType.Name
  148. }
  149. // 检查map中是否有对应的值
  150. strValue, ok := configMap[key]
  151. if !ok {
  152. continue
  153. }
  154. // 根据字段类型设置值
  155. if !field.CanSet() {
  156. continue
  157. }
  158. switch field.Kind() {
  159. case reflect.String:
  160. field.SetString(strValue)
  161. case reflect.Bool:
  162. boolValue, err := strconv.ParseBool(strValue)
  163. if err != nil {
  164. continue
  165. }
  166. field.SetBool(boolValue)
  167. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  168. intValue, err := strconv.ParseInt(strValue, 10, 64)
  169. if err != nil {
  170. continue
  171. }
  172. field.SetInt(intValue)
  173. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
  174. uintValue, err := strconv.ParseUint(strValue, 10, 64)
  175. if err != nil {
  176. continue
  177. }
  178. field.SetUint(uintValue)
  179. case reflect.Float32, reflect.Float64:
  180. floatValue, err := strconv.ParseFloat(strValue, 64)
  181. if err != nil {
  182. continue
  183. }
  184. field.SetFloat(floatValue)
  185. case reflect.Map, reflect.Slice, reflect.Struct:
  186. // 复杂类型使用JSON反序列化
  187. err := json.Unmarshal([]byte(strValue), field.Addr().Interface())
  188. if err != nil {
  189. continue
  190. }
  191. }
  192. }
  193. return nil
  194. }
  195. // ConfigToMap 将配置对象转换为map(导出函数)
  196. func ConfigToMap(config interface{}) (map[string]string, error) {
  197. return configToMap(config)
  198. }
  199. // UpdateConfigFromMap 从map更新配置对象(导出函数)
  200. func UpdateConfigFromMap(config interface{}, configMap map[string]string) error {
  201. return updateConfigFromMap(config, configMap)
  202. }
  203. // ExportAllConfigs 导出所有已注册的配置为扁平结构
  204. func (cm *ConfigManager) ExportAllConfigs() map[string]string {
  205. cm.mutex.RLock()
  206. defer cm.mutex.RUnlock()
  207. result := make(map[string]string)
  208. for name, cfg := range cm.configs {
  209. configMap, err := ConfigToMap(cfg)
  210. if err != nil {
  211. continue
  212. }
  213. // 使用 "模块名.配置项" 的格式添加到结果中
  214. for key, value := range configMap {
  215. result[name+"."+key] = value
  216. }
  217. }
  218. return result
  219. }