diff --git a/controller/system/iml.go b/controller/system/iml.go index c471a6c4..72e0de8f 100644 --- a/controller/system/iml.go +++ b/controller/system/iml.go @@ -5,16 +5,20 @@ import ( "bytes" "encoding/json" "fmt" + "net/http" + "time" + + system_dto "github.com/APIParkLab/APIPark/module/system/dto" + application_authorization "github.com/APIParkLab/APIPark/module/application-authorization" "github.com/APIParkLab/APIPark/module/catalogue" "github.com/APIParkLab/APIPark/module/router" "github.com/APIParkLab/APIPark/module/service" "github.com/APIParkLab/APIPark/module/subscribe" + "github.com/APIParkLab/APIPark/module/system" "github.com/APIParkLab/APIPark/module/team" "github.com/APIParkLab/APIPark/module/upstream" "github.com/gin-gonic/gin" - "net/http" - "time" ) var _ IExportConfigController = (*imlExportConfigController)(nil) @@ -165,3 +169,19 @@ func (i *imlExportConfigController) appendFiles(ctx *gin.Context) ([]*ExportFile return files, nil } + +var ( + _ ISettingController = (*imlSettingController)(nil) +) + +type imlSettingController struct { + settingModule system.ISettingModule `autowired:""` +} + +func (i *imlSettingController) Get(ctx *gin.Context) (*system_dto.Setting, error) { + return i.settingModule.Get(ctx), nil +} + +func (i *imlSettingController) Set(ctx *gin.Context, input *system_dto.InputSetting) error { + return i.settingModule.Set(ctx, input) +} diff --git a/controller/system/system.go b/controller/system/system.go index 49cc93c3..008bf5d0 100644 --- a/controller/system/system.go +++ b/controller/system/system.go @@ -1,9 +1,11 @@ package system import ( + "reflect" + + system_dto "github.com/APIParkLab/APIPark/module/system/dto" "github.com/eolinker/go-common/autowire" "github.com/gin-gonic/gin" - "reflect" ) type IExportConfigController interface { @@ -14,6 +16,11 @@ type IImportConfigController interface { ImportAll(ctx *gin.Context) error } +type ISettingController interface { + Get(ctx *gin.Context) (*system_dto.Setting, error) + Set(ctx *gin.Context, input *system_dto.InputSetting) error +} + func init() { autowire.Auto[IExportConfigController](func() reflect.Value { return reflect.ValueOf(new(imlExportConfigController)) @@ -22,4 +29,8 @@ func init() { autowire.Auto[IImportConfigController](func() reflect.Value { return reflect.ValueOf(new(imlImportConfigController)) }) + + autowire.Auto[ISettingController](func() reflect.Value { + return reflect.ValueOf(new(imlSettingController)) + }) } diff --git a/module/system/dto/input.go b/module/system/dto/input.go new file mode 100644 index 00000000..23230ba1 --- /dev/null +++ b/module/system/dto/input.go @@ -0,0 +1,40 @@ +package system_dto + +import ( + "net/url" + "reflect" +) + +type InputSetting struct { + InvokeAddress string `json:"invoke_address" key:"system.node.invoke_address"` +} + +func (i *InputSetting) Validate() error { + _, err := url.Parse(i.InvokeAddress) + if err != nil { + return err + } + return nil +} + +func ToKeyMap(i interface{}) map[string]string { + result := make(map[string]string) + val := reflect.ValueOf(i) + typ := reflect.TypeOf(i) + if typ.Kind() == reflect.Ptr { + val = val.Elem() + typ = typ.Elem() + } + switch typ.Kind() { + case reflect.Struct: + { + for i := 0; i < typ.NumField(); i++ { + f := typ.Field(i) + if f.Tag.Get("key") != "" { + result[f.Tag.Get("key")] = val.Field(i).String() + } + } + } + } + return result +} diff --git a/module/system/dto/input_test.go b/module/system/dto/input_test.go new file mode 100644 index 00000000..e33908ed --- /dev/null +++ b/module/system/dto/input_test.go @@ -0,0 +1,18 @@ +package system_dto + +import ( + "log" + "testing" +) + +func TestMap(t *testing.T) { + + input := &InputSetting{ + InvokeAddress: "http://127.0.0.1:8080", + } + err := input.Validate() + if err != nil { + t.Error(err) + } + log.Println(ToKeyMap(input)) +} diff --git a/module/system/dto/output.go b/module/system/dto/output.go new file mode 100644 index 00000000..b1d9a36d --- /dev/null +++ b/module/system/dto/output.go @@ -0,0 +1,63 @@ +package system_dto + +import ( + "reflect" + "strconv" +) + +type Setting struct { + InvokeAddress string `json:"invoke_address" key:"system.node.invoke_address"` +} + +func MapStringToStruct[T any](m map[string]string) *T { + var result T + val := reflect.ValueOf(&result).Elem() + + // 获取结构体的类型 + t := val.Type() + + // 查找结构体中与键名匹配的字段 + for i := 0; i < t.NumField(); i++ { + field := t.Field(i) + key := field.Tag.Get("key") + if key == "" { + continue + } + v, ok := m[key] + if !ok { + continue + } + // 获取字段的值 + fieldVal := val.Field(i) + if !fieldVal.CanSet() { + continue + } + fieldVal.SetString(v) + + // 如果字段不可设置,跳过 + if !fieldVal.CanSet() { + continue + } + + // 根据字段的类型,进行类型转换 + switch fieldVal.Kind() { + case reflect.Float64: + // 如果是 string 类型且非空,转换为 float64 + if floatVal, err := strconv.ParseFloat(v, 64); err == nil { + fieldVal.SetFloat(floatVal) + } + + case reflect.Int: + + if intVal, err := strconv.Atoi(v); err == nil { + fieldVal.SetInt(int64(intVal)) + } + case reflect.String: + fieldVal.SetString(v) + default: + // 其他类型不进行转换 + } + } + + return &result +} diff --git a/module/system/iml.go b/module/system/iml.go new file mode 100644 index 00000000..b83cefe5 --- /dev/null +++ b/module/system/iml.go @@ -0,0 +1,48 @@ +package system + +import ( + "context" + + "github.com/eolinker/go-common/store" + + "github.com/eolinker/go-common/utils" + + system_dto "github.com/APIParkLab/APIPark/module/system/dto" + "github.com/APIParkLab/APIPark/service/setting" +) + +var ( + _ ISettingModule = (*imlSettingModule)(nil) +) + +type imlSettingModule struct { + settingService setting.ISettingService `autowired:""` + transaction store.ITransaction `autowired:""` +} + +func (i *imlSettingModule) Get(ctx context.Context) *system_dto.Setting { + v, err := i.settingService.All(ctx) + if err != nil { + return &system_dto.Setting{} + } + return system_dto.MapStringToStruct[system_dto.Setting](v) +} + +func (i *imlSettingModule) Set(ctx context.Context, input *system_dto.InputSetting) error { + err := input.Validate() + if err != nil { + return err + } + + return i.transaction.Transaction(ctx, func(ctx context.Context) error { + keyMap := system_dto.ToKeyMap(input) + userId := utils.UserId(ctx) + for k, v := range keyMap { + err = i.settingService.Set(ctx, k, v, userId) + if err != nil { + return err + } + } + return nil + }) +} diff --git a/module/system/system.go b/module/system/system.go index 411cec1e..8625d02e 100644 --- a/module/system/system.go +++ b/module/system/system.go @@ -1,7 +1,26 @@ package system -import "context" +import ( + "context" + "reflect" + + "github.com/eolinker/go-common/autowire" + + system_dto "github.com/APIParkLab/APIPark/module/system/dto" +) type IExportModule[T any] interface { ExportAll(ctx context.Context) ([]*T, error) } + +type ISettingModule interface { + Get(ctx context.Context) *system_dto.Setting + Set(ctx context.Context, input *system_dto.InputSetting) error +} + +func init() { + autowire.Auto[ISettingModule](func() reflect.Value { + return reflect.ValueOf(new(imlSettingModule)) + }) + +} diff --git a/plugins/core/core.go b/plugins/core/core.go index c116a2bb..2be3ebef 100644 --- a/plugins/core/core.go +++ b/plugins/core/core.go @@ -1,12 +1,13 @@ package core import ( + "net/http" + "github.com/APIParkLab/APIPark/controller/ai" ai_api "github.com/APIParkLab/APIPark/controller/ai-api" "github.com/APIParkLab/APIPark/controller/monitor" "github.com/APIParkLab/APIPark/controller/router" "github.com/APIParkLab/APIPark/controller/system" - "net/http" plugin_cluster "github.com/APIParkLab/APIPark/controller/plugin-cluster" @@ -81,6 +82,7 @@ type plugin struct { exportConfigController system.IExportConfigController `autowired:""` importConfigController system.IImportConfigController `autowired:""` aiProviderController ai.IProviderController `autowired:""` + settingController system.ISettingController `autowired:""` apis []pm3.Api } diff --git a/plugins/core/system.go b/plugins/core/system.go index a90fc16f..a44a921c 100644 --- a/plugins/core/system.go +++ b/plugins/core/system.go @@ -1,13 +1,17 @@ package core import ( - "github.com/eolinker/go-common/pm3" "net/http" + + "github.com/eolinker/go-common/pm3" ) func (p *plugin) systemApis() []pm3.Api { return []pm3.Api{ pm3.CreateApiWidthDoc(http.MethodGet, "/api/v1/system/_export", []string{"context"}, nil, p.exportConfigController.ExportAll), pm3.CreateApiWidthDoc(http.MethodGet, "/api/v1/system/_import", []string{"context"}, nil, p.importConfigController.ImportAll), + + pm3.CreateApiWidthDoc(http.MethodGet, "/api/v1/system/general", []string{"context"}, []string{"general"}, p.settingController.Get), + pm3.CreateApiWidthDoc(http.MethodPost, "/api/v1/system/general", []string{"context", "body"}, nil, p.settingController.Set), } } diff --git a/service/setting/iml.go b/service/setting/iml.go index 82768c53..a7dc8a0a 100644 --- a/service/setting/iml.go +++ b/service/setting/iml.go @@ -2,6 +2,9 @@ package setting import ( "context" + + "github.com/eolinker/go-common/utils" + "github.com/APIParkLab/APIPark/stores/setting" ) @@ -13,6 +16,16 @@ type imlSettingService struct { store setting.ISettingStore `autowired:""` } +func (i *imlSettingService) All(ctx context.Context) (map[string]string, error) { + list, err := i.store.All(ctx) + if err != nil { + return nil, err + } + return utils.SliceToMapO(list, func(v *setting.Setting) (string, string) { + return v.Name, v.Value + }), nil +} + func (i *imlSettingService) Get(ctx context.Context, name string) (string, bool) { ev, err := i.store.Get(ctx, name) if err != nil { @@ -22,6 +35,6 @@ func (i *imlSettingService) Get(ctx context.Context, name string) (string, bool) } func (i *imlSettingService) Set(ctx context.Context, name string, value string, operator string) error { - + return i.store.Set(ctx, name, value, operator) } diff --git a/service/setting/setting.go b/service/setting/setting.go index 2a306766..e1954f4a 100644 --- a/service/setting/setting.go +++ b/service/setting/setting.go @@ -2,14 +2,15 @@ package setting import ( "context" - "github.com/eolinker/go-common/autowire" "reflect" + + "github.com/eolinker/go-common/autowire" ) type ISettingService interface { Get(ctx context.Context, name string) (value string, has bool) Set(ctx context.Context, name string, value string, operator string) error - //All(ctx context.Context) map[string]string + All(ctx context.Context) (map[string]string, error) } func init() { diff --git a/stores/setting/store.go b/stores/setting/store.go index 3b8989c9..66b6be1e 100644 --- a/stores/setting/store.go +++ b/stores/setting/store.go @@ -3,11 +3,12 @@ package setting import ( "context" "errors" + "reflect" + "time" + "github.com/eolinker/go-common/autowire" "github.com/eolinker/go-common/store" "gorm.io/gorm" - "reflect" - "time" ) var ( @@ -17,11 +18,16 @@ var ( type ISettingStore interface { Get(ctx context.Context, name string) (*Setting, error) Set(ctx context.Context, name string, value string, operator string) error + All(ctx context.Context) ([]*Setting, error) } type imlSettingStore struct { store.Store[Setting] } +func (i *imlSettingStore) All(ctx context.Context) ([]*Setting, error) { + return i.Store.List(ctx, nil) +} + func (i *imlSettingStore) Get(ctx context.Context, name string) (*Setting, error) { return i.Store.First(ctx, map[string]interface{}{"name": name}) }