diff --git a/admin/apps/game/boot.go b/admin/apps/game/boot.go index 1a92228..d5bf3e5 100644 --- a/admin/apps/game/boot.go +++ b/admin/apps/game/boot.go @@ -8,14 +8,14 @@ import ( ) func initFun(app *node.Application) error { - svc := service.NewCmdServerSvc(global.GLOB_DB) // 初始化应用服务 - srv := server.New(svc) // 初始化http服务 - srv.Route(global.GLOB_API_ENGINE) // 初始化http服务路由 + svc := service.New(global.GLOB_DB) // 初始化应用服务 + srv := server.New(svc) // 初始化http服务 + srv.Route(global.GLOB_API_ENGINE) // 初始化http服务路由 return nil } func New() *node.ApplicationDescInfo { - app := node.NewApplicationDescInfo("user", initFun) + app := node.NewApplicationDescInfo("game", initFun) return app } diff --git a/admin/apps/game/domain/entity/project.go b/admin/apps/game/domain/entity/project.go index 87d39ed..1a6e577 100644 --- a/admin/apps/game/domain/entity/project.go +++ b/admin/apps/game/domain/entity/project.go @@ -3,6 +3,7 @@ package entity import ( "admin/apps/game/model" "admin/apps/game/model/dto" + "math/rand" "reflect" ) @@ -31,13 +32,17 @@ func FromProjectDto(dto dto.CommonDtoValues) *Project { po := et.po //to := reflect.TypeOf(po) - vo := reflect.ValueOf(po) + vo := reflect.ValueOf(po).Elem() + to := reflect.TypeOf(po).Elem() for k, v := range dto { fo := vo.FieldByName(k) - fo.Set(reflect.ValueOf(v)) + ft, _ := to.FieldByName(k) + fo.Set(parseStr2FieldValue(ft, v)) } + et.Id = po.ID + return et } @@ -77,7 +82,7 @@ func (et *Project) GetDtoFieldsDescInfo() []*dto.CommonDtoFieldDesc { Type: ft.Type.Name(), HelpText: ft.Tag.Get("desc"), Editable: true, - Require: true, + Require: rand.Int()%2 == 0, Choices: make([]*dto.CommonDtoFieldChoice, 0), MultiChoice: false, } diff --git a/admin/apps/game/domain/entity/server.go b/admin/apps/game/domain/entity/server.go index 0e321a4..b158cc7 100644 --- a/admin/apps/game/domain/entity/server.go +++ b/admin/apps/game/domain/entity/server.go @@ -38,6 +38,8 @@ func FromServerDto(dto dto.CommonDtoValues) *Server { fo.Set(reflect.ValueOf(v)) } + et.Id = po.ID + return et } diff --git a/admin/apps/game/domain/entity/utils.go b/admin/apps/game/domain/entity/utils.go new file mode 100644 index 0000000..cc1c8e3 --- /dev/null +++ b/admin/apps/game/domain/entity/utils.go @@ -0,0 +1,68 @@ +package entity + +import ( + "fmt" + "gorm.io/gorm" + "reflect" + "strconv" + "time" +) + +func parseStr2FieldValue(field reflect.StructField, rawValue any) (realSetValue reflect.Value) { + setValue := fmt.Sprintf("%v", rawValue) + var parsedValue any + switch field.Type.Kind() { + case reflect.Int: + v, _ := strconv.Atoi(setValue) + parsedValue = int(v) + case reflect.Int32: + v, _ := strconv.Atoi(setValue) + parsedValue = int32(v) + case reflect.Int8: + v, _ := strconv.Atoi(setValue) + parsedValue = int8(v) + case reflect.Int16: + v, _ := strconv.Atoi(setValue) + parsedValue = int16(v) + case reflect.Int64: + v, _ := strconv.Atoi(setValue) + parsedValue = int64(v) + case reflect.Uint: + v, _ := strconv.Atoi(setValue) + parsedValue = uint(v) + case reflect.Uint8: + v, _ := strconv.Atoi(setValue) + parsedValue = uint(v) + case reflect.Uint16: + v, _ := strconv.Atoi(setValue) + parsedValue = uint16(v) + case reflect.Uint32: + v, _ := strconv.Atoi(setValue) + parsedValue = uint32(v) + case reflect.Uint64: + v, _ := strconv.Atoi(setValue) + parsedValue = uint64(v) + case reflect.Bool: + parsedValue = setValue == "true" + case reflect.String: + parsedValue = setValue + case reflect.Float32: + v, _ := strconv.ParseFloat(setValue, 10) + parsedValue = float32(v) + case reflect.Float64: + v, _ := strconv.ParseFloat(setValue, 10) + parsedValue = float64(v) + case reflect.Struct: + typeName := field.Type.Name() + if typeName == "Time" { + return reflect.ValueOf(time.Now()) + } + if typeName == "DeletedAt" { + return reflect.ValueOf(gorm.DeletedAt{}) + } + fallthrough + default: + panic(fmt.Errorf("暂时不支持的前后端交互字段类型:%v, 类型名:%v", field.Type.Kind(), field.Type.Name())) + } + return reflect.ValueOf(parsedValue) +} diff --git a/admin/apps/game/domain/repo/project.go b/admin/apps/game/domain/repo/project.go index 361a20c..9e789cf 100644 --- a/admin/apps/game/domain/repo/project.go +++ b/admin/apps/game/domain/repo/project.go @@ -34,12 +34,12 @@ func (repo *projectRepoImpl) List(pageNo, pageLen int) ([]*entity.Project, error } // debug - list = append(list, &model.Project{ - ID: 123, - Name: "神魔大陆", - Desc: "神魔大陆服务器", - ApiAddr: "http://192.168.1.1:8081", - }) + //list = append(list, &model.Project{ + // ID: 123, + // Name: "神魔大陆", + // Desc: "神魔大陆服务器", + // ApiAddr: "http://192.168.1.1:8081", + //}) entityList := make([]*entity.Project, 0, len(list)) for _, Project := range list { diff --git a/admin/apps/game/model/dto/common.go b/admin/apps/game/model/dto/common.go index 6f994f5..a296593 100644 --- a/admin/apps/game/model/dto/common.go +++ b/admin/apps/game/model/dto/common.go @@ -31,3 +31,8 @@ type CommonDtoList struct { FieldsDesc []*CommonDtoFieldDesc `json:"fields_desc"` // 数据字段描述信息 Rows []CommonDtoValues `json:"rows"` // 数据行 } + +type PathInfo struct { + Path string `json:"path"` + Method string `json:"method"` +} diff --git a/admin/apps/game/model/dto/msg.go b/admin/apps/game/model/dto/msg.go new file mode 100644 index 0000000..d4179cf --- /dev/null +++ b/admin/apps/game/model/dto/msg.go @@ -0,0 +1,45 @@ +package dto + +type NilReq struct { +} + +type NilRsp = NilReq + +type CommonListReq struct { + PageNo int `json:"page_no"` + PageLen int `json:"page_len"` +} + +type CommonPostReq struct { + Dto *CommonDtoValues `json:"dto"` +} + +type CommonPutReq struct { + Dto *CommonDtoValues `json:"dto"` +} + +type CommonDeleteReq struct { + Id int `json:"id"` +} + +type CommonListRsp = CommonDtoList + +type CommonPostRsp struct { + Dto *CommonDtoValues `json:"dto"` +} + +type CommonPutRsp struct { + Dto *CommonDtoValues `json:"dto"` +} + +type CommonDeleteRsp struct { + Id int `json:"id"` +} + +type CommandListReq struct { + Addr string `json:"addr"` +} + +type CommandListRsp struct { + List []*PathInfo `json:"list"` +} diff --git a/admin/apps/game/model/dto/response.go b/admin/apps/game/model/dto/response.go deleted file mode 100644 index 95538ee..0000000 --- a/admin/apps/game/model/dto/response.go +++ /dev/null @@ -1,3 +0,0 @@ -package dto - -type CommonListRsp = CommonDtoList diff --git a/admin/apps/game/server/ctl_common_rest.go b/admin/apps/game/server/ctl_common_rest.go index 90e8f59..1e292d3 100644 --- a/admin/apps/game/server/ctl_common_rest.go +++ b/admin/apps/game/server/ctl_common_rest.go @@ -5,38 +5,37 @@ import ( "admin/internal/context" ) -func (ctl *controller) CommonList(ctx *context.WebContext, restfulResourceName string, params *dto.CommonListReq) { +func (ctl *controller) CommonList(ctx *context.WebContext, restfulResourceName string, params *dto.CommonListReq, rsp *dto.CommonListRsp) error { list, err := ctl.svc.CommonList(ctx, restfulResourceName, params) if err != nil { - ctx.Fail(err) - return + return err } - ctx.Ok(list) + *rsp = *list + return nil } -func (ctl *controller) CommonPost(ctx *context.WebContext, restfulResourceName string, params *dto.CommonDtoValues) { - newObj, err := ctl.svc.CommonPost(ctx, restfulResourceName, *params) +func (ctl *controller) CommonPost(ctx *context.WebContext, restfulResourceName string, params *dto.CommonPostReq, rsp *dto.CommonPostRsp) error { + newObj, err := ctl.svc.CommonPost(ctx, restfulResourceName, *params.Dto) if err != nil { - ctx.Fail(err) - return + return err } - ctx.Ok(newObj) + rsp.Dto = &newObj + return nil } -func (ctl *controller) CommonPut(ctx *context.WebContext, restfulResourceName string, params *dto.CommonDtoValues) { - newObj, err := ctl.svc.CommonPut(ctx, restfulResourceName, *params) +func (ctl *controller) CommonPut(ctx *context.WebContext, restfulResourceName string, params *dto.CommonPutReq, rsp *dto.CommonPutRsp) error { + newObj, err := ctl.svc.CommonPut(ctx, restfulResourceName, *params.Dto) if err != nil { - ctx.Fail(err) - return + return err } - ctx.Ok(newObj) + rsp.Dto = &newObj + return nil } -func (ctl *controller) CommonDelete(ctx *context.WebContext, restfulResourceName string, id int) { - err := ctl.svc.CommonDelete(ctx, restfulResourceName, id) +func (ctl *controller) CommonDelete(ctx *context.WebContext, restfulResourceName string, params *dto.CommonDeleteReq, rsp *dto.CommonDeleteRsp) error { + err := ctl.svc.CommonDelete(ctx, restfulResourceName, params.Id) if err != nil { - ctx.Fail(err) - return + return err } - ctx.Ok(nil) + return nil } diff --git a/admin/apps/game/server/ctl_game.go b/admin/apps/game/server/ctl_game.go new file mode 100644 index 0000000..bdb08aa --- /dev/null +++ b/admin/apps/game/server/ctl_game.go @@ -0,0 +1,31 @@ +package server + +import ( + "admin/apps/game/model/dto" + "admin/internal/context" + "admin/lib/httpclient" + "admin/lib/xlog" +) + +func (ctl *controller) CommandList(ctx *context.WebContext, params *dto.CommandListReq, rsp *dto.CommandListRsp) error { + + url := params.Addr + "/api/commandlist" + + xlog.Debugf("request url:%v command list", url) + + cmdListRsp := make(map[string]any) + err := httpclient.Request(url, "get", nil, &cmdListRsp) + if err != nil { + return err + } + + xlog.Debugf("command list rsp:%+v", cmdListRsp) + + ctx.Ok(cmdListRsp) + + return nil +} + +func (ctl *controller) apiRequest() { + +} diff --git a/admin/apps/game/server/route.go b/admin/apps/game/server/route.go index 46f92ee..4ba5076 100644 --- a/admin/apps/game/server/route.go +++ b/admin/apps/game/server/route.go @@ -3,55 +3,57 @@ package server import ( "admin/apps/game/model/dto" "admin/internal/context" + "admin/internal/global" "admin/lib/web" ) func (srv *Server) Route(engine *web.Engine) { - apiGroup := engine.Group("/api") + apiGroup := engine.Group("/api", "") srv.proRoute(apiGroup) srv.serverRoute(apiGroup) + + { + apiGroup.Get("/project/commandlist", "调用对应游戏服api获取命令列表", global.WebPathPermit_Read, srv.ctl.CommandList) + } } -func (srv *Server) proRoute(engine *web.Group) { +func (srv *Server) proRoute(engine *web.RoutesGroup) { resourceName := "project" - proGroup := engine.Group("/" + resourceName) - - proGroup.Get("", "获取项目列表", web.AccessMode_Read, dto.CommonListReq{}, commonHandlerList(srv.ctl, resourceName)) - proGroup.Post("", "新增项目", web.AccessMode_Read, dto.CommonPostReq{}, commonHandlerList(srv.ctl, resourceName)) - proGroup.Put("", "修改项目", web.AccessMode_Read, dto.CommonPutReq{}, commonHandlerList(srv.ctl, resourceName)) - proGroup.Delete("", "删除项目", web.AccessMode_Read, dto.CommonDeleteReq{}, commonHandlerList(srv.ctl, resourceName)) + srv.registerResourceRouter(resourceName, engine.Group("/"+resourceName, "")) } -func (srv *Server) serverRoute(engine *web.Group) { +func (srv *Server) serverRoute(engine *web.RoutesGroup) { resourceName := "server" - proGroup := engine.Group("/" + resourceName) - - proGroup.Get("", "获取服务器列表", web.AccessMode_Read, dto.CommonListReq{}, commonHandlerList(srv.ctl, resourceName)) - proGroup.Post("", "新增服务器", web.AccessMode_Read, dto.CommonPostReq{}, commonHandlerList(srv.ctl, resourceName)) - proGroup.Put("", "修改服务器", web.AccessMode_Read, dto.CommonPutReq{}, commonHandlerList(srv.ctl, resourceName)) - proGroup.Delete("", "删除服务器", web.AccessMode_Read, dto.CommonDeleteReq{}, commonHandlerList(srv.ctl, resourceName)) + srv.registerResourceRouter(resourceName, engine.Group("/"+resourceName, "")) } -func commonHandlerList(ctl *controller, resourceName string) func(ctx *context.WebContext, params *dto.CommonListReq) { - return func(ctx *context.WebContext, params *dto.CommonListReq) { - ctl.CommonList(ctx, resourceName, params) +func (srv *Server) registerResourceRouter(resourceName string, group *web.RoutesGroup) { + group.Get("", "获取列表", global.WebPathPermit_Read, commonHandlerList(srv.ctl, resourceName)) + group.Post("", "新增", global.WebPathPermit_Read, commonHandlerPost(srv.ctl, resourceName)) + group.Put("", "修改", global.WebPathPermit_Read, commonHandlerPut(srv.ctl, resourceName)) + group.Delete("", "删除", global.WebPathPermit_Read, commonHandlerDelete(srv.ctl, resourceName)) +} + +func commonHandlerList(ctl *controller, resourceName string) func(ctx *context.WebContext, params *dto.CommonListReq, rsp *dto.CommonListRsp) error { + return func(ctx *context.WebContext, params *dto.CommonListReq, rsp *dto.CommonListRsp) error { + return ctl.CommonList(ctx, resourceName, params, rsp) } } -func commonHandlerPost(ctl *controller, resourceName string) func(ctx *context.WebContext, params *dto.CommonPostReq) { - return func(ctx *context.WebContext, params *dto.CommonPostReq) { - ctl.CommonPost(ctx, resourceName, params.Dto) +func commonHandlerPost(ctl *controller, resourceName string) func(ctx *context.WebContext, params *dto.CommonPostReq, rsp *dto.CommonPostRsp) error { + return func(ctx *context.WebContext, params *dto.CommonPostReq, rsp *dto.CommonPostRsp) error { + return ctl.CommonPost(ctx, resourceName, params, rsp) } } -func commonHandlerPut(ctl *controller, resourceName string) func(ctx *context.WebContext, params *dto.CommonPutReq) { - return func(ctx *context.WebContext, params *dto.CommonPutReq) { - ctl.CommonPut(ctx, resourceName, params.Dto) +func commonHandlerPut(ctl *controller, resourceName string) func(ctx *context.WebContext, params *dto.CommonPutReq, rsp *dto.CommonPutRsp) error { + return func(ctx *context.WebContext, params *dto.CommonPutReq, rsp *dto.CommonPutRsp) error { + return ctl.CommonPut(ctx, resourceName, params, rsp) } } -func commonHandlerDelete(ctl *controller, resourceName string) func(ctx *context.WebContext, params *dto.CommonDeleteReq) { - return func(ctx *context.WebContext, params *dto.CommonDeleteReq) { - ctl.CommonDelete(ctx, resourceName, params.Id) +func commonHandlerDelete(ctl *controller, resourceName string) func(ctx *context.WebContext, params *dto.CommonDeleteReq, rsp *dto.CommonDeleteRsp) error { + return func(ctx *context.WebContext, params *dto.CommonDeleteReq, rsp *dto.CommonDeleteRsp) error { + return ctl.CommonDelete(ctx, resourceName, params, rsp) } } diff --git a/admin/apps/game/service/service.go b/admin/apps/game/service/service.go index cfa5cf6..b953b40 100644 --- a/admin/apps/game/service/service.go +++ b/admin/apps/game/service/service.go @@ -13,7 +13,7 @@ type Service struct { serverSvc *domain.ServerSvc } -func NewCmdServerSvc(db *gorm.DB) *Service { +func New(db *gorm.DB) *Service { return &Service{ db: db, projectSvc: domain.NewProjectSvc(db), diff --git a/admin/apps/mockpro/boot.go b/admin/apps/mockpro/boot.go new file mode 100644 index 0000000..7747d8b --- /dev/null +++ b/admin/apps/mockpro/boot.go @@ -0,0 +1,28 @@ +package mockpro + +import ( + internalGlobal "admin/apps/mockpro/internal/global" + "admin/apps/mockpro/server" + "admin/apps/mockpro/service" + "admin/internal/global" + "admin/lib/node" +) + +func initFun(app *node.Application) error { + internalGlobal.GLOB_DB = global.GLOB_DB + svc := service.New(global.GLOB_DB) + server.New(svc) // 初始化http服务 + return nil +} + +func New() *node.ApplicationDescInfo { + app := node.NewApplicationDescInfo("mock_project", initFun). + WithOptions(node.WithAppBootFlag(internalGlobal.GLOB_BOOT_FLAGS)) + return app +} + +func must(err error) { + if err != nil { + panic(err) + } +} diff --git a/admin/apps/mockpro/domain/ban.go b/admin/apps/mockpro/domain/ban.go new file mode 100644 index 0000000..9d5b5eb --- /dev/null +++ b/admin/apps/mockpro/domain/ban.go @@ -0,0 +1,48 @@ +package domain + +import ( + "admin/apps/mockpro/domain/entity" + "admin/apps/mockpro/domain/repo" + "admin/apps/mockpro/internal/model/dto" + "gorm.io/gorm" +) + +type BanSvc struct { + BanRepo repo.IBanRepo +} + +func NewBanSvc(db *gorm.DB) *BanSvc { + svc := &BanSvc{ + BanRepo: repo.NewBanRepo(db), + } + registerRestfulSvc("ban", svc) + return svc +} + +func (svc *BanSvc) List(pageNo, pageLen int) ([]*dto.CommonDtoFieldDesc, []IRestfulEntity, error) { + entityList, err := svc.BanRepo.List(pageNo, pageLen) + if err != nil { + return nil, nil, err + } + iList := make([]IRestfulEntity, 0, len(entityList)) + for _, v := range entityList { + iList = append(iList, v) + } + return entity.BanDtoFieldsDescInfo, iList, nil +} + +func (svc *BanSvc) Post(obj dto.CommonDtoValues) (IRestfulEntity, error) { + et := entity.FromBanDto(obj) + err := svc.BanRepo.Create(et) + return et, err +} + +func (svc *BanSvc) Put(obj dto.CommonDtoValues) (IRestfulEntity, error) { + et := entity.FromBanDto(obj) + err := svc.BanRepo.Edit(et) + return et, err +} + +func (svc *BanSvc) Delete(id int) error { + return svc.BanRepo.Delete(id) +} diff --git a/admin/apps/mockpro/domain/entity/server.go b/admin/apps/mockpro/domain/entity/server.go new file mode 100644 index 0000000..e953551 --- /dev/null +++ b/admin/apps/mockpro/domain/entity/server.go @@ -0,0 +1,89 @@ +package entity + +import ( + "admin/apps/mockpro/internal/model" + "admin/apps/mockpro/internal/model/dto" + "reflect" +) + +var BanDtoFieldsDescInfo = DefaultBan().GetDtoFieldsDescInfo() + +type Ban struct { + Id int + po *model.Ban +} + +func DefaultBan() *Ban { + return &Ban{ + po: &model.Ban{}, + } +} + +func FromBanPo(po *model.Ban) *Ban { + return &Ban{ + Id: po.ID, + po: po, + } +} + +func FromBanDto(dto dto.CommonDtoValues) *Ban { + et := DefaultBan() + po := et.po + + //to := reflect.TypeOf(po) + vo := reflect.ValueOf(po) + + for k, v := range dto { + fo := vo.FieldByName(k) + fo.Set(reflect.ValueOf(v)) + } + + return et +} + +func (et *Ban) ToPo() *model.Ban { + return et.po +} + +func (et *Ban) ToCommonDto() dto.CommonDtoValues { + obj := make(dto.CommonDtoValues) + + to := reflect.TypeOf(et.po).Elem() + vo := reflect.ValueOf(et.po).Elem() + for i := 0; i < vo.NumField(); i++ { + ft := to.Field(i) + fo := vo.Field(i) + + obj[ft.Name] = fo.Interface() + } + + return obj +} + +func (et *Ban) GetDtoFieldsDescInfo() []*dto.CommonDtoFieldDesc { + + to := reflect.TypeOf(et.po).Elem() + vo := reflect.ValueOf(et.po).Elem() + + obj := make([]*dto.CommonDtoFieldDesc, 0, to.NumField()) + + for i := 0; i < vo.NumField(); i++ { + ft := to.Field(i) + //fo := vo.Field(i) + + f1 := &dto.CommonDtoFieldDesc{ + Name: ft.Name, + Key: ft.Name, + Type: ft.Type.Name(), + HelpText: ft.Tag.Get("desc"), + Editable: true, + Require: true, + Choices: make([]*dto.CommonDtoFieldChoice, 0), + MultiChoice: false, + } + + obj = append(obj, f1) + } + + return obj +} diff --git a/admin/apps/mockpro/domain/entity/whitelist.go b/admin/apps/mockpro/domain/entity/whitelist.go new file mode 100644 index 0000000..1eec71c --- /dev/null +++ b/admin/apps/mockpro/domain/entity/whitelist.go @@ -0,0 +1,89 @@ +package entity + +import ( + "admin/apps/mockpro/internal/model" + "admin/apps/mockpro/internal/model/dto" + "reflect" +) + +var WhiteListDtoFieldsDescInfo = DefaultWhiteList().GetDtoFieldsDescInfo() + +type WhiteList struct { + Id int + po *model.WhiteList +} + +func DefaultWhiteList() *WhiteList { + return &WhiteList{ + po: &model.WhiteList{}, + } +} + +func FromWhiteListPo(po *model.WhiteList) *WhiteList { + return &WhiteList{ + Id: po.ID, + po: po, + } +} + +func FromWhiteListDto(dto dto.CommonDtoValues) *WhiteList { + et := DefaultWhiteList() + po := et.po + + //to := reflect.TypeOf(po) + vo := reflect.ValueOf(po) + + for k, v := range dto { + fo := vo.FieldByName(k) + fo.Set(reflect.ValueOf(v)) + } + + return et +} + +func (et *WhiteList) ToPo() *model.WhiteList { + return et.po +} + +func (et *WhiteList) ToCommonDto() dto.CommonDtoValues { + obj := make(dto.CommonDtoValues) + + to := reflect.TypeOf(et.po).Elem() + vo := reflect.ValueOf(et.po).Elem() + for i := 0; i < vo.NumField(); i++ { + ft := to.Field(i) + fo := vo.Field(i) + + obj[ft.Name] = fo.Interface() + } + + return obj +} + +func (et *WhiteList) GetDtoFieldsDescInfo() []*dto.CommonDtoFieldDesc { + + to := reflect.TypeOf(et.po).Elem() + vo := reflect.ValueOf(et.po).Elem() + + obj := make([]*dto.CommonDtoFieldDesc, 0, to.NumField()) + + for i := 0; i < vo.NumField(); i++ { + ft := to.Field(i) + //fo := vo.Field(i) + + f1 := &dto.CommonDtoFieldDesc{ + Name: ft.Name, + Key: ft.Name, + Type: ft.Type.Name(), + HelpText: ft.Tag.Get("desc"), + Editable: true, + Require: true, + Choices: make([]*dto.CommonDtoFieldChoice, 0), + MultiChoice: false, + } + + obj = append(obj, f1) + } + + return obj +} diff --git a/admin/apps/mockpro/domain/irestfull.go b/admin/apps/mockpro/domain/irestfull.go new file mode 100644 index 0000000..6e427ae --- /dev/null +++ b/admin/apps/mockpro/domain/irestfull.go @@ -0,0 +1,31 @@ +package domain + +import ( + "admin/apps/mockpro/internal/model/dto" + "admin/internal/errcode" +) + +type IRestfulEntity interface { + ToCommonDto() dto.CommonDtoValues +} + +type IRestfulResourceSvc interface { + List(pageNo, pageLen int) ([]*dto.CommonDtoFieldDesc, []IRestfulEntity, error) + Post(obj dto.CommonDtoValues) (IRestfulEntity, error) + Put(obj dto.CommonDtoValues) (IRestfulEntity, error) + Delete(id int) error +} + +var restfulResourceSvcMgr = make(map[string]IRestfulResourceSvc) + +func registerRestfulSvc(name string, svc IRestfulResourceSvc) { + restfulResourceSvcMgr[name] = svc +} + +func FindRestfulResourceSvc(name string) (IRestfulResourceSvc, error) { + svc, find := restfulResourceSvcMgr[name] + if !find { + return nil, errcode.New(errcode.ServerError, "not found %v restful svc", name) + } + return svc, nil +} diff --git a/admin/apps/mockpro/domain/repo/ban.go b/admin/apps/mockpro/domain/repo/ban.go new file mode 100644 index 0000000..94ce678 --- /dev/null +++ b/admin/apps/mockpro/domain/repo/ban.go @@ -0,0 +1,69 @@ +package repo + +import ( + "admin/apps/mockpro/domain/entity" + "admin/apps/mockpro/internal/model" + "admin/internal/errcode" + "gorm.io/gorm" +) + +type IBanRepo interface { + List(pageNo, pageLen int) ([]*entity.Ban, error) + Create(et *entity.Ban) error + Edit(et *entity.Ban) error + Delete(id int) error +} + +func NewBanRepo(db *gorm.DB) IBanRepo { + return newBanRepoImpl(db) +} + +type BanRepoImpl struct { + db *gorm.DB +} + +func newBanRepoImpl(db *gorm.DB) *BanRepoImpl { + return &BanRepoImpl{db: db} +} + +func (repo *BanRepoImpl) List(pageNo, pageLen int) ([]*entity.Ban, error) { + list := make([]*model.Ban, 0) + err := repo.db.Find(&list).Error + if err != nil { + return nil, errcode.New(errcode.DBError, "find Ban error:%v", err) + } + + entityList := make([]*entity.Ban, 0, len(list)) + for _, Ban := range list { + entityList = append(entityList, entity.FromBanPo(Ban)) + } + + return entityList, nil +} + +func (repo *BanRepoImpl) Create(et *entity.Ban) error { + po := et.ToPo() + err := repo.db.Create(po).Error + if err != nil { + return errcode.New(errcode.DBError, "create obj:%+v error:%v", et, err) + } + et.Id = po.ID + return nil +} + +func (repo *BanRepoImpl) Edit(et *entity.Ban) error { + po := et.ToPo() + err := repo.db.Where("id=?", et.Id).Updates(po).Error + if err != nil { + return errcode.New(errcode.DBError, "edit obj:%+v error:%v", et, err) + } + return nil +} + +func (repo *BanRepoImpl) Delete(id int) error { + err := repo.db.Where("id=?", id).Unscoped().Delete(&model.Ban{}).Error + if err != nil { + return errcode.New(errcode.DBError, "delete obj:%+v error:%v", id, err) + } + return nil +} diff --git a/admin/apps/mockpro/domain/repo/whitelist.go b/admin/apps/mockpro/domain/repo/whitelist.go new file mode 100644 index 0000000..6d5ee62 --- /dev/null +++ b/admin/apps/mockpro/domain/repo/whitelist.go @@ -0,0 +1,69 @@ +package repo + +import ( + "admin/apps/mockpro/domain/entity" + "admin/apps/mockpro/internal/model" + "admin/internal/errcode" + "gorm.io/gorm" +) + +type IWhiteListRepo interface { + List(pageNo, pageLen int) ([]*entity.WhiteList, error) + Create(et *entity.WhiteList) error + Edit(et *entity.WhiteList) error + Delete(id int) error +} + +func NewWhiteListRepo(db *gorm.DB) IWhiteListRepo { + return newWhiteListRepoImpl(db) +} + +type WhiteListRepoImpl struct { + db *gorm.DB +} + +func newWhiteListRepoImpl(db *gorm.DB) *WhiteListRepoImpl { + return &WhiteListRepoImpl{db: db} +} + +func (repo *WhiteListRepoImpl) List(pageNo, pageLen int) ([]*entity.WhiteList, error) { + list := make([]*model.WhiteList, 0) + err := repo.db.Find(&list).Error + if err != nil { + return nil, errcode.New(errcode.DBError, "find WhiteList error:%v", err) + } + + entityList := make([]*entity.WhiteList, 0, len(list)) + for _, WhiteList := range list { + entityList = append(entityList, entity.FromWhiteListPo(WhiteList)) + } + + return entityList, nil +} + +func (repo *WhiteListRepoImpl) Create(et *entity.WhiteList) error { + po := et.ToPo() + err := repo.db.Create(po).Error + if err != nil { + return errcode.New(errcode.DBError, "create obj:%+v error:%v", et, err) + } + et.Id = po.ID + return nil +} + +func (repo *WhiteListRepoImpl) Edit(et *entity.WhiteList) error { + po := et.ToPo() + err := repo.db.Where("id=?", et.Id).Updates(po).Error + if err != nil { + return errcode.New(errcode.DBError, "edit obj:%+v error:%v", et, err) + } + return nil +} + +func (repo *WhiteListRepoImpl) Delete(id int) error { + err := repo.db.Where("id=?", id).Unscoped().Delete(&model.WhiteList{}).Error + if err != nil { + return errcode.New(errcode.DBError, "delete obj:%+v error:%v", id, err) + } + return nil +} diff --git a/admin/apps/mockpro/domain/whitelist.go b/admin/apps/mockpro/domain/whitelist.go new file mode 100644 index 0000000..baacaf7 --- /dev/null +++ b/admin/apps/mockpro/domain/whitelist.go @@ -0,0 +1,48 @@ +package domain + +import ( + "admin/apps/mockpro/domain/entity" + "admin/apps/mockpro/domain/repo" + "admin/apps/mockpro/internal/model/dto" + "gorm.io/gorm" +) + +type WhiteListSvc struct { + proRepo repo.IWhiteListRepo +} + +func NewWhiteListSvc(db *gorm.DB) *WhiteListSvc { + svc := &WhiteListSvc{ + proRepo: repo.NewWhiteListRepo(db), + } + registerRestfulSvc("whitelist", svc) + return svc +} + +func (svc *WhiteListSvc) List(pageNo, pageLen int) ([]*dto.CommonDtoFieldDesc, []IRestfulEntity, error) { + entityList, err := svc.proRepo.List(pageNo, pageLen) + if err != nil { + return nil, nil, err + } + iList := make([]IRestfulEntity, 0, len(entityList)) + for _, v := range entityList { + iList = append(iList, v) + } + return entity.WhiteListDtoFieldsDescInfo, iList, nil +} + +func (svc *WhiteListSvc) Post(obj dto.CommonDtoValues) (IRestfulEntity, error) { + et := entity.FromWhiteListDto(obj) + err := svc.proRepo.Create(et) + return et, err +} + +func (svc *WhiteListSvc) Put(obj dto.CommonDtoValues) (IRestfulEntity, error) { + et := entity.FromWhiteListDto(obj) + err := svc.proRepo.Edit(et) + return et, err +} + +func (svc *WhiteListSvc) Delete(id int) error { + return svc.proRepo.Delete(id) +} diff --git a/admin/apps/mockpro/internal/config/flags.go b/admin/apps/mockpro/internal/config/flags.go new file mode 100644 index 0000000..04a5261 --- /dev/null +++ b/admin/apps/mockpro/internal/config/flags.go @@ -0,0 +1,5 @@ +package config + +type MockBootFlags struct { + ApiPort string `env:"mock_api_port" default:"8654" desc:"api端口,客户端请求的地址端口"` +} diff --git a/admin/apps/mockpro/internal/global/var.go b/admin/apps/mockpro/internal/global/var.go new file mode 100644 index 0000000..5b4022a --- /dev/null +++ b/admin/apps/mockpro/internal/global/var.go @@ -0,0 +1,11 @@ +package global + +import ( + "admin/apps/mockpro/internal/config" + "gorm.io/gorm" +) + +var ( + GLOB_BOOT_FLAGS = &config.MockBootFlags{} + GLOB_DB *gorm.DB +) diff --git a/admin/apps/mockpro/internal/model/account.go b/admin/apps/mockpro/internal/model/account.go new file mode 100644 index 0000000..524e052 --- /dev/null +++ b/admin/apps/mockpro/internal/model/account.go @@ -0,0 +1,20 @@ +package model + +import ( + "admin/internal/db" + "gorm.io/gorm" + "time" +) + +func init() { + db.RegisterTableModels(Account{}) +} + +type Account struct { + ID int `gorm:"primarykey"` + Account string `gorm:"primarykey"` + + CreatedAt time.Time + UpdatedAt time.Time + DeletedAt gorm.DeletedAt `gorm:"index"` +} diff --git a/admin/apps/mockpro/internal/model/ban.go b/admin/apps/mockpro/internal/model/ban.go new file mode 100644 index 0000000..0701e4a --- /dev/null +++ b/admin/apps/mockpro/internal/model/ban.go @@ -0,0 +1,22 @@ +package model + +import ( + "admin/internal/db" + "gorm.io/gorm" + "time" +) + +func init() { + db.RegisterTableModels(Ban{}) +} + +type Ban struct { + ID int `gorm:"primarykey"` + BanType string + Value string + ExpireSeconds int + + CreatedAt time.Time + UpdatedAt time.Time + DeletedAt gorm.DeletedAt `gorm:"index"` +} diff --git a/admin/apps/mockpro/internal/model/devicepush.go b/admin/apps/mockpro/internal/model/devicepush.go new file mode 100644 index 0000000..fc53060 --- /dev/null +++ b/admin/apps/mockpro/internal/model/devicepush.go @@ -0,0 +1,22 @@ +package model + +import ( + "admin/internal/db" + "gorm.io/gorm" + "time" +) + +func init() { + db.RegisterTableModels(DevicePush{}) +} + +type DevicePush struct { + ID int `gorm:"primarykey"` + Account string + Title string + Content string + + CreatedAt time.Time + UpdatedAt time.Time + DeletedAt gorm.DeletedAt `gorm:"index"` +} diff --git a/admin/apps/mockpro/internal/model/dto/common.go b/admin/apps/mockpro/internal/model/dto/common.go new file mode 100644 index 0000000..6f994f5 --- /dev/null +++ b/admin/apps/mockpro/internal/model/dto/common.go @@ -0,0 +1,33 @@ +package dto + +type CommonDtoFieldChoice struct { + Desc string `json:"desc"` + Value any `json:"value"` + // 描述选项的类型,例如添加物品时,可以添加道具、翅膀、宠物等,他们可能不一定都设计为道具 + Type int `json:"type"` +} + +type CommonDtoFieldDesc struct { + Name string `json:"name"` + Key string `json:"key"` + // 字段类型,基础类型支持int float string bool []<基础类行>, + // 支持自定义类型和自定义类型的数组 + Type string `json:"type"` + HelpText string `json:"help_text"` + Editable bool `json:"editable"` // 是否可编辑,例如id就不可编辑,新增时也不需要填写 + Require bool `json:"require"` // 是否必填,不能为空 + Choices []*CommonDtoFieldChoice `json:"choices"` // 可选项,用于字段做下拉框 + MultiChoice bool `json:"multi_choice"` // 是否多选 +} + +//type CommonDtoValue struct { +// FieldName string `json:"field_name"` +// Value any `json:"value"` +//} + +type CommonDtoValues map[string]any + +type CommonDtoList struct { + FieldsDesc []*CommonDtoFieldDesc `json:"fields_desc"` // 数据字段描述信息 + Rows []CommonDtoValues `json:"rows"` // 数据行 +} diff --git a/admin/apps/game/model/dto/request.go b/admin/apps/mockpro/internal/model/dto/msg.go similarity index 51% rename from admin/apps/game/model/dto/request.go rename to admin/apps/mockpro/internal/model/dto/msg.go index 9bf54ab..8ee41bd 100644 --- a/admin/apps/game/model/dto/request.go +++ b/admin/apps/mockpro/internal/model/dto/msg.go @@ -1,5 +1,11 @@ package dto +type NilReq struct { +} + +type NilRsp struct { +} + type CommonListReq struct { PageNo int `json:"page_no"` PageLen int `json:"page_len"` @@ -16,3 +22,17 @@ type CommonPutReq struct { type CommonDeleteReq struct { Id int `json:"id"` } + +type CommonListRsp = CommonDtoList + +type CommonPostRsp struct { + Dto *CommonDtoValues `json:"dto"` +} + +type CommonPutRsp struct { + Dto *CommonDtoValues `json:"dto"` +} + +type CommonDeleteRsp struct { + Id int `json:"id"` +} diff --git a/admin/apps/mockpro/internal/model/globalmail.go b/admin/apps/mockpro/internal/model/globalmail.go new file mode 100644 index 0000000..422ee08 --- /dev/null +++ b/admin/apps/mockpro/internal/model/globalmail.go @@ -0,0 +1,23 @@ +package model + +import ( + "admin/internal/db" + "gorm.io/gorm" + "time" +) + +func init() { + db.RegisterTableModels(GlobalMail{}) +} + +type GlobalMail struct { + ID int `gorm:"primarykey"` + ServerIDs []int `gorm:"type:json;serializer:json"` + Title string + Content string + Attach []*MailAttachItem `gorm:"type:json;serializer:json"` + + CreatedAt time.Time + UpdatedAt time.Time + DeletedAt gorm.DeletedAt `gorm:"index"` +} diff --git a/admin/apps/mockpro/internal/model/notice.go b/admin/apps/mockpro/internal/model/notice.go new file mode 100644 index 0000000..83e43bf --- /dev/null +++ b/admin/apps/mockpro/internal/model/notice.go @@ -0,0 +1,23 @@ +package model + +import ( + "admin/internal/db" + "gorm.io/gorm" + "time" +) + +func init() { + db.RegisterTableModels(Notice{}) +} + +type Notice struct { + ID int `gorm:"primarykey"` + ServerIDs []int `gorm:"type:json;serializer:json"` + Content string + StartAt int64 + EndAt int64 + + CreatedAt time.Time + UpdatedAt time.Time + DeletedAt gorm.DeletedAt `gorm:"index"` +} diff --git a/admin/apps/mockpro/internal/model/order.go b/admin/apps/mockpro/internal/model/order.go new file mode 100644 index 0000000..9274538 --- /dev/null +++ b/admin/apps/mockpro/internal/model/order.go @@ -0,0 +1,24 @@ +package model + +import ( + "admin/internal/db" + "gorm.io/gorm" + "time" +) + +func init() { + db.RegisterTableModels(Order{}) +} + +type Order struct { + ID int `gorm:"primarykey"` + RoleID string + Account string + Price int + Currency int + GoodID int + + CreatedAt time.Time + UpdatedAt time.Time + DeletedAt gorm.DeletedAt `gorm:"index"` +} diff --git a/admin/apps/mockpro/internal/model/rewardcode.go b/admin/apps/mockpro/internal/model/rewardcode.go new file mode 100644 index 0000000..393a8fb --- /dev/null +++ b/admin/apps/mockpro/internal/model/rewardcode.go @@ -0,0 +1,21 @@ +package model + +import ( + "admin/internal/db" + "gorm.io/gorm" + "time" +) + +func init() { + db.RegisterTableModels(RewardCode{}) +} + +type RewardCode struct { + ID int `gorm:"primarykey"` + Group int + Code int + + CreatedAt time.Time + UpdatedAt time.Time + DeletedAt gorm.DeletedAt `gorm:"index"` +} diff --git a/admin/apps/mockpro/internal/model/role.go b/admin/apps/mockpro/internal/model/role.go new file mode 100644 index 0000000..7af6a99 --- /dev/null +++ b/admin/apps/mockpro/internal/model/role.go @@ -0,0 +1,22 @@ +package model + +import ( + "admin/internal/db" + "gorm.io/gorm" + "time" +) + +func init() { + db.RegisterTableModels(Role{}) +} + +type Role struct { + ID int `gorm:"primarykey"` + RoleID string + Name string + Account string `gorm:"primarykey"` + + CreatedAt time.Time + UpdatedAt time.Time + DeletedAt gorm.DeletedAt `gorm:"index"` +} diff --git a/admin/apps/mockpro/internal/model/rolemail.go b/admin/apps/mockpro/internal/model/rolemail.go new file mode 100644 index 0000000..3e946a2 --- /dev/null +++ b/admin/apps/mockpro/internal/model/rolemail.go @@ -0,0 +1,30 @@ +package model + +import ( + "admin/internal/db" + "gorm.io/gorm" + "time" +) + +func init() { + db.RegisterTableModels(RoleMail{}) +} + +type MailAttachItem struct { + ID int32 + Num int64 + ItemType int +} + +type RoleMail struct { + ID int `gorm:"primarykey"` + RoleIDs string + ServerID int + Title string + Content string + Attach []*MailAttachItem `gorm:"type:json;serializer:json"` + + CreatedAt time.Time + UpdatedAt time.Time + DeletedAt gorm.DeletedAt `gorm:"index"` +} diff --git a/admin/apps/mockpro/internal/model/whitelist.go b/admin/apps/mockpro/internal/model/whitelist.go new file mode 100644 index 0000000..14bda69 --- /dev/null +++ b/admin/apps/mockpro/internal/model/whitelist.go @@ -0,0 +1,22 @@ +package model + +import ( + "admin/internal/db" + "gorm.io/gorm" + "time" +) + +func init() { + db.RegisterTableModels(WhiteList{}) +} + +type WhiteList struct { + ID int `gorm:"primarykey"` + Account string `gorm:"primarykey"` + AccountType int + Desc string + + CreatedAt time.Time + UpdatedAt time.Time + DeletedAt gorm.DeletedAt `gorm:"index"` +} diff --git a/admin/apps/mockpro/server/ctl.go b/admin/apps/mockpro/server/ctl.go new file mode 100644 index 0000000..0fe38ab --- /dev/null +++ b/admin/apps/mockpro/server/ctl.go @@ -0,0 +1,11 @@ +package server + +import "admin/apps/mockpro/service" + +type controller struct { + svc *service.Service +} + +func newController(svc *service.Service) *controller { + return &controller{svc: svc} +} diff --git a/admin/apps/mockpro/server/ctl_mock.go b/admin/apps/mockpro/server/ctl_mock.go new file mode 100644 index 0000000..724070b --- /dev/null +++ b/admin/apps/mockpro/server/ctl_mock.go @@ -0,0 +1,40 @@ +package server + +import ( + dto2 "admin/apps/mockpro/internal/model/dto" +) + +func (ctl *controller) CommonList(ctx *WebContext, restfulResourceName string, params *dto2.CommonListReq, rsp *dto2.CommonListRsp) error { + list, err := ctl.svc.CommonList(ctx, restfulResourceName, params) + if err != nil { + return err + } + *rsp = *list + return nil +} + +func (ctl *controller) CommonPost(ctx *WebContext, restfulResourceName string, params *dto2.CommonPostReq, rsp *dto2.CommonPostRsp) error { + newObj, err := ctl.svc.CommonPost(ctx, restfulResourceName, *params.Dto) + if err != nil { + return err + } + rsp.Dto = &newObj + return nil +} + +func (ctl *controller) CommonPut(ctx *WebContext, restfulResourceName string, params *dto2.CommonPutReq, rsp *dto2.CommonPutRsp) error { + newObj, err := ctl.svc.CommonPut(ctx, restfulResourceName, *params.Dto) + if err != nil { + return err + } + rsp.Dto = &newObj + return nil +} + +func (ctl *controller) CommonDelete(ctx *WebContext, restfulResourceName string, params *dto2.CommonDeleteReq, rsp *dto2.CommonDeleteRsp) error { + err := ctl.svc.CommonDelete(ctx, restfulResourceName, params.Id) + if err != nil { + return err + } + return nil +} diff --git a/admin/apps/mockpro/server/ctx_web.go b/admin/apps/mockpro/server/ctx_web.go new file mode 100644 index 0000000..e15587b --- /dev/null +++ b/admin/apps/mockpro/server/ctx_web.go @@ -0,0 +1,43 @@ +package server + +import ( + "admin/internal/errcode" + "admin/lib/web" + "context" + "github.com/gin-gonic/gin" +) + +type WebContext struct { + context.Context + rawCtx *gin.Context +} + +func NewWebContext(rawCtx *gin.Context) web.IContext { + return &WebContext{rawCtx: rawCtx} +} + +func (ctx *WebContext) Ok(data any) { + ctx.rawCtx.JSON(200, map[string]any{ + "code": 200, + "msg": "", + "data": data, + }) +} + +func (ctx *WebContext) Fail(err error) { + code, stack, msg := errcode.ParseError(err) + ctx.rawCtx.JSON(200, map[string]any{ + "code": code, + "stack": stack, + "msg": msg, + "data": "", + }) +} + +func (ctx *WebContext) HandleError(path string, err error) { + ctx.Fail(err) +} + +func (ctx *WebContext) HandleSuccess(rspData any) { + ctx.Ok(rspData) +} diff --git a/admin/apps/mockpro/server/route.go b/admin/apps/mockpro/server/route.go new file mode 100644 index 0000000..257a79e --- /dev/null +++ b/admin/apps/mockpro/server/route.go @@ -0,0 +1,105 @@ +package server + +import ( + "admin/apps/mockpro/internal/model/dto" + "admin/internal/global" + "admin/lib/web" +) + +func (srv *Server) Route(engine *web.Engine) { + apiGroup := engine.Group("/api", "") + { + srv.whitelist(apiGroup) + srv.ban(apiGroup) + srv.rolemail(apiGroup) + srv.globalmail(apiGroup) + srv.account(apiGroup) + srv.role(apiGroup) + srv.order(apiGroup) + srv.notice(apiGroup) + srv.rewardcode(apiGroup) + srv.devicepush(apiGroup) + } + apiGroup.Get("/commandlist", "获取项目所有gm指令描述", global.WebPathPermit_Read, srv.commandlist) +} + +func (srv *Server) whitelist(engine *web.RoutesGroup) { + resourceName := "whitelist" + srv.registerResourceRouter(resourceName, engine.Group("/"+resourceName, "白名单管理")) +} + +func (srv *Server) ban(engine *web.RoutesGroup) { + resourceName := "ban" + srv.registerResourceRouter(resourceName, engine.Group("/"+resourceName, "封禁管理")) +} + +func (srv *Server) rolemail(engine *web.RoutesGroup) { + resourceName := "rolemail" + srv.registerResourceRouter(resourceName, engine.Group("/"+resourceName, "个人邮件")) +} + +func (srv *Server) globalmail(engine *web.RoutesGroup) { + resourceName := "globalmail" + srv.registerResourceRouter(resourceName, engine.Group("/"+resourceName, "全服邮件")) +} + +func (srv *Server) account(engine *web.RoutesGroup) { + resourceName := "account" + srv.registerResourceRouter(resourceName, engine.Group("/"+resourceName, "账号管理")) +} + +func (srv *Server) role(engine *web.RoutesGroup) { + resourceName := "role" + srv.registerResourceRouter(resourceName, engine.Group("/"+resourceName, "角色管理")) +} + +func (srv *Server) order(engine *web.RoutesGroup) { + resourceName := "order" + srv.registerResourceRouter(resourceName, engine.Group("/"+resourceName, "订单管理")) +} + +func (srv *Server) notice(engine *web.RoutesGroup) { + resourceName := "notice" + srv.registerResourceRouter(resourceName, engine.Group("/"+resourceName, "公告管理")) +} + +func (srv *Server) rewardcode(engine *web.RoutesGroup) { + resourceName := "rewardcode" + srv.registerResourceRouter(resourceName, engine.Group("/"+resourceName, "奖励码")) +} + +func (srv *Server) devicepush(engine *web.RoutesGroup) { + resourceName := "devicepush" + srv.registerResourceRouter(resourceName, engine.Group("/"+resourceName, "设备推送")) +} + +func (srv *Server) registerResourceRouter(resourceName string, group *web.RoutesGroup) { + group.Get("", "获取列表", global.WebPathPermit_Read, commonHandlerList(srv.ctl, resourceName)) + group.Post("", "新增", global.WebPathPermit_Read, commonHandlerPost(srv.ctl, resourceName)) + group.Put("", "修改", global.WebPathPermit_Read, commonHandlerPut(srv.ctl, resourceName)) + group.Delete("", "删除", global.WebPathPermit_Read, commonHandlerDelete(srv.ctl, resourceName)) +} + +func commonHandlerList(ctl *controller, resourceName string) func(ctx *WebContext, params *dto.CommonListReq, rsp *dto.CommonListRsp) error { + return func(ctx *WebContext, params *dto.CommonListReq, rsp *dto.CommonListRsp) error { + return ctl.CommonList(ctx, resourceName, params, rsp) + } +} + +func commonHandlerPost(ctl *controller, resourceName string) func(ctx *WebContext, params *dto.CommonPostReq, rsp *dto.CommonPostRsp) error { + return func(ctx *WebContext, params *dto.CommonPostReq, rsp *dto.CommonPostRsp) error { + return ctl.CommonPost(ctx, resourceName, params, rsp) + } +} + +func commonHandlerPut(ctl *controller, resourceName string) func(ctx *WebContext, params *dto.CommonPutReq, rsp *dto.CommonPutRsp) error { + return func(ctx *WebContext, params *dto.CommonPutReq, rsp *dto.CommonPutRsp) error { + return ctl.CommonPut(ctx, resourceName, params, rsp) + } +} + +func commonHandlerDelete(ctl *controller, resourceName string) func(ctx *WebContext, params *dto.CommonDeleteReq, rsp *dto.CommonDeleteRsp) error { + return func(ctx *WebContext, params *dto.CommonDeleteReq, rsp *dto.CommonDeleteRsp) error { + return ctl.CommonDelete(ctx, resourceName, params, rsp) + } +} diff --git a/admin/apps/mockpro/server/route_desc.go b/admin/apps/mockpro/server/route_desc.go new file mode 100644 index 0000000..fbdcd38 --- /dev/null +++ b/admin/apps/mockpro/server/route_desc.go @@ -0,0 +1,48 @@ +package server + +import ( + "admin/apps/mockpro/internal/model/dto" + "admin/lib/web" +) + +type PathInfo struct { + Path string `json:"path"` + Method string `json:"method"` +} +type ResourceInfo struct { + Desc string `json:"desc"` + Paths []*PathInfo `json:"paths"` +} +type CmdListRsp struct { + List []*ResourceInfo `json:"list"` +} + +func (srv *Server) commandlist(ctx *WebContext, req *dto.NilReq, rsp *CmdListRsp) error { + paths := make([]*ResourceInfo, 0) + srv.engine.TravelPaths(func(path string, parentDesc string, method string, handlers ...web.HandlerFunc) { + find := false + for _, v := range paths { + if v.Desc == parentDesc { + v.Paths = append(v.Paths, &PathInfo{ + Path: path, + Method: method, + }) + find = true + break + } + } + if !find { + paths = append(paths, &ResourceInfo{ + Desc: parentDesc, + Paths: []*PathInfo{ + &PathInfo{ + Path: path, + Method: method, + }, + }, + }) + } + }) + rsp.List = paths + return nil +} diff --git a/admin/apps/mockpro/server/server.go b/admin/apps/mockpro/server/server.go new file mode 100644 index 0000000..441fdf5 --- /dev/null +++ b/admin/apps/mockpro/server/server.go @@ -0,0 +1,29 @@ +package server + +import ( + "admin/apps/mockpro/internal/global" + "admin/apps/mockpro/service" + "admin/lib/web" +) + +type Server struct { + engine *web.Engine + svc *service.Service + ctl *controller +} + +func New(svc *service.Service) *Server { + engine := web.New(NewWebContext) + srv := &Server{ + engine: engine, + ctl: newController(svc), + } + srv.Route(engine) + go func() { + err := engine.Run(":" + global.GLOB_BOOT_FLAGS.ApiPort) + if err != nil { + panic(err) + } + }() + return srv +} diff --git a/admin/apps/mockpro/service/service.go b/admin/apps/mockpro/service/service.go new file mode 100644 index 0000000..8fc963d --- /dev/null +++ b/admin/apps/mockpro/service/service.go @@ -0,0 +1,68 @@ +package service + +import ( + "admin/apps/mockpro/domain" + dto2 "admin/apps/mockpro/internal/model/dto" + "context" + "gorm.io/gorm" +) + +type Service struct { + db *gorm.DB + whitelistSvc *domain.WhiteListSvc + banSvc *domain.BanSvc +} + +func New(db *gorm.DB) *Service { + return &Service{ + db: db, + whitelistSvc: domain.NewWhiteListSvc(db), + banSvc: domain.NewBanSvc(db), + } +} + +func (svc *Service) CommonList(ctx context.Context, resourceName string, params *dto2.CommonListReq) (*dto2.CommonDtoList, error) { + restfulDomainSvc, err := domain.FindRestfulResourceSvc(resourceName) + if err != nil { + return nil, err + } + dtoFieldsDescInfo, list, err := restfulDomainSvc.List(params.PageNo, params.PageLen) + if err != nil { + return nil, err + } + retList := make([]dto2.CommonDtoValues, 0, len(list)) + for _, v := range list { + retList = append(retList, v.ToCommonDto()) + } + return &dto2.CommonDtoList{FieldsDesc: dtoFieldsDescInfo, Rows: retList}, nil +} + +func (svc *Service) CommonPost(ctx context.Context, resourceName string, params dto2.CommonDtoValues) (dto2.CommonDtoValues, error) { + restfulDomainSvc, err := domain.FindRestfulResourceSvc(resourceName) + if err != nil { + return nil, err + } + et, err := restfulDomainSvc.Post(params) + if err != nil { + return nil, err + } + return et.ToCommonDto(), nil +} +func (svc *Service) CommonPut(ctx context.Context, resourceName string, params dto2.CommonDtoValues) (dto2.CommonDtoValues, error) { + restfulDomainSvc, err := domain.FindRestfulResourceSvc(resourceName) + if err != nil { + return nil, err + } + et, err := restfulDomainSvc.Put(params) + if err != nil { + return nil, err + } + return et.ToCommonDto(), nil +} +func (svc *Service) CommonDelete(ctx context.Context, resourceName string, id int) error { + restfulDomainSvc, err := domain.FindRestfulResourceSvc(resourceName) + if err != nil { + return err + } + return restfulDomainSvc.Delete(id) +} diff --git a/admin/cmd/all_in_one/main.go b/admin/cmd/all_in_one/main.go index c073490..ea3a78b 100644 --- a/admin/cmd/all_in_one/main.go +++ b/admin/cmd/all_in_one/main.go @@ -2,6 +2,7 @@ package main import ( "admin/apps/game" + "admin/apps/mockpro" "admin/internal/mynode" "admin/lib/node" ) @@ -11,6 +12,7 @@ var appList []*node.ApplicationDescInfo func init() { appList = []*node.ApplicationDescInfo{ game.New(), + mockpro.New(), } } diff --git a/admin/internal/context/ctx_web.go b/admin/internal/context/ctx_web.go index 8ae820b..1ebfa59 100644 --- a/admin/internal/context/ctx_web.go +++ b/admin/internal/context/ctx_web.go @@ -3,41 +3,55 @@ package context import ( "admin/internal/errcode" "admin/lib/web" + "admin/lib/xlog" "context" + "github.com/gin-gonic/gin" ) type WebContext struct { context.Context - rawCtx web.RawContext + rawCtx *gin.Context + alreadySetRsp bool } -func NewWebContext() web.Context { - return &WebContext{} +func NewWebContext(rawCtx *gin.Context) web.IContext { + return &WebContext{rawCtx: rawCtx} } func (ctx *WebContext) Ok(data any) { - ctx.rawCtx.Json(200, map[string]any{ + if ctx.alreadySetRsp { + return + } + + ctx.rawCtx.JSON(200, map[string]any{ "code": 200, "msg": "", "data": data, }) + + ctx.alreadySetRsp = true } func (ctx *WebContext) Fail(err error) { + if ctx.alreadySetRsp { + return + } + code, stack, msg := errcode.ParseError(err) - ctx.rawCtx.Json(200, map[string]any{ + ctx.rawCtx.JSON(200, map[string]any{ "code": code, "stack": stack, "msg": msg, "data": "", }) + + ctx.alreadySetRsp = true } -func (ctx *WebContext) SetRawContext(rawCtx web.RawContext) { - ctx.Context = context.Background() - ctx.rawCtx = rawCtx +func (ctx *WebContext) HandleError(path string, err error) { + xlog.Errorf("path:%v handle error:%v ", path, err) + ctx.Fail(err) } - -func (ctx *WebContext) GetRawContext() web.RawContext { - return ctx.rawCtx +func (ctx *WebContext) HandleSuccess(rspData any) { + ctx.Ok(rspData) } diff --git a/admin/internal/db/db.go b/admin/internal/db/db.go index 4426b9b..6a4a445 100644 --- a/admin/internal/db/db.go +++ b/admin/internal/db/db.go @@ -118,7 +118,7 @@ func tryCreateDB(dbName, dsn string) (string, error) { db.Raw("SELECT COUNT(*) FROM information_schema.schemata WHERE schema_name = ?", dbName).Scan(&count) if count == 0 { // 数据库不存在,创建它 - sql := fmt.Sprintf(`create database if not exists %s default charset utf8mb4 collate utf8mb4_unicode_ci`, + sql := fmt.Sprintf("create database if not exists `%s` default charset utf8mb4 collate utf8mb4_unicode_ci", dbName) if e := db.Exec(sql).Error; e != nil { return "", fmt.Errorf("failed to create database:%v", e) diff --git a/admin/internal/global/consts.go b/admin/internal/global/consts.go new file mode 100644 index 0000000..3d58b45 --- /dev/null +++ b/admin/internal/global/consts.go @@ -0,0 +1,6 @@ +package global + +const ( + WebPathPermit_Read = 1 + WebPathPermit_Write = 2 +) diff --git a/admin/internal/mynode/node.go b/admin/internal/mynode/node.go index f239c3e..fc4803f 100644 --- a/admin/internal/mynode/node.go +++ b/admin/internal/mynode/node.go @@ -14,7 +14,7 @@ func New() *node.Node { nd.ApplyOptions(node.WithNodeExBootFlags(global.GLOB_BOOT_FLAGS)) nd.AddInitTask("初始化全局api监听服务", func() error { - global.GLOB_API_ENGINE = web.NewEngine("gin", context.NewWebContext) + global.GLOB_API_ENGINE = web.New(context.NewWebContext) return nil }) diff --git a/admin/lib/httpclient/client.go b/admin/lib/httpclient/client.go new file mode 100644 index 0000000..6330346 --- /dev/null +++ b/admin/lib/httpclient/client.go @@ -0,0 +1,73 @@ +package httpclient + +import ( + "admin/internal/errcode" + "admin/lib/xlog" + "encoding/json" + "io" + "net/http" + "strings" + "time" +) + +func Request(addr string, method string, body interface{}, resData interface{}) error { + removeUrl := checkUrl(addr) + + //xlog.Debugf("-->req url: %v", removeUrl) + var res *http.Response + var err error + if method != "get" { + var bodyReader io.Reader + if body != nil { + bodyBytes, err := json.Marshal(body) + if err != nil { + xlog.Warnf(err) + return errcode.New(errcode.ServerError, "数据解析失败:%v", err) + } + bodyReader = strings.NewReader(string(bodyBytes)) + } + client := &http.Client{ + Timeout: time.Second * 3, + } + req, err := http.NewRequest(method, removeUrl, bodyReader) + if err != nil { + xlog.Warnf(err) + return errcode.New(errcode.ServerError, "数据请求创建失败:%v", err) + } + + res, err = client.Do(req) + if err != nil { + xlog.Warnf(err) + return errcode.New(errcode.ServerError, "数据请求失败:%v", err) + } + } else { + res, err = http.Get(removeUrl) + } + + // 获取数据 + defer res.Body.Close() + + resBody, err := io.ReadAll(res.Body) + if err != nil { + xlog.Warnf(err) + return errcode.New(errcode.ServerError, "数据解析失败:%v", err) + } + + xlog.Debugf("request url:%v, rsp:%v", removeUrl, string(resBody)) + + if err = json.Unmarshal(resBody, resData); err != nil { + return errcode.New(errcode.ServerError, "数据(%v)格式错误:%v", string(resBody), err) + } + + //xlog.Debugf("%+v", resData) + + return nil +} + +func checkUrl(u string) string { + if strings.Contains(u, `http://`) || strings.Contains(u, `https://`) { + return u + } else { + return `http://` + u + } +} diff --git a/admin/lib/node/node_init.go b/admin/lib/node/node_init.go index f3bcf38..a5eae47 100644 --- a/admin/lib/node/node_init.go +++ b/admin/lib/node/node_init.go @@ -112,7 +112,7 @@ func (node *Node) initBootConfig() error { } func (node *Node) initLog() error { - logConfig := &LogBootConfig{} + logConfig := DefaultLogBootConfig() if node.bootConfigFile.globalBootConfigFileContent != nil { logConfig = node.bootConfigFile.globalBootConfigFileContent.GetLogConfig().Check() } diff --git a/admin/lib/node/node_log.go b/admin/lib/node/node_log.go index 0acbc4d..2736154 100644 --- a/admin/lib/node/node_log.go +++ b/admin/lib/node/node_log.go @@ -16,6 +16,12 @@ type LogBootConfig struct { LogLevel string `yaml:"log_level"` // 日志等级: trace/debug/info/notice/warn/error/fatal } +func DefaultLogBootConfig() *LogBootConfig { + return &LogBootConfig{ + LogLevel: "trace", + } +} + func (lc *LogBootConfig) Check() *LogBootConfig { if lc.LogDir == "" { lc.LogDir = "./logs" diff --git a/admin/lib/web/desc.go b/admin/lib/web/desc.go new file mode 100644 index 0000000..ef6cacb --- /dev/null +++ b/admin/lib/web/desc.go @@ -0,0 +1,57 @@ +package web + +type routesPath struct { + method string // get|post|put|delete + desc string + permit int + handlers []HandlerFunc +} + +type routesNode struct { + path string + methods []*routesPath + child []*routesNode +} + +func newRoutesNode(method, path string, desc string, permit int, handlers ...HandlerFunc) *routesNode { + n := &routesNode{ + path: path, + } + n.addMethod(method, desc, permit, handlers) + return n +} + +func (n *routesNode) addChildren(method, path string, desc string, permit int, handlers ...HandlerFunc) *routesNode { + for _, c := range n.child { + if c.path == path { + c.addMethod(method, desc, permit, handlers) + return c + } + } + + children := newRoutesNode(method, path, desc, permit, handlers) + n.child = append(n.child, children) + return children +} + +func (n *routesNode) addMethod(method string, desc string, permit int, handlers ...HandlerFunc) *routesNode { + n.methods = append(n.methods, &routesPath{method: method, desc: desc, permit: permit, handlers: handlers}) + return n +} + +func (n *routesNode) travel(parentPath string, parentDesc string, travelFun func(parentDesc string, path string, method string, handlers ...HandlerFunc)) { + curPath := parentPath + n.path + curNodeDesc := "" + if len(n.methods) > 0 { + for _, method := range n.methods { + if method.method == "" { + curNodeDesc = method.desc + continue + } + travelFun(curPath, parentDesc, method.method, method.handlers) + } + } + for _, c := range n.child { + c.travel(curPath, curNodeDesc, travelFun) + } +} diff --git a/admin/lib/web/engine.go b/admin/lib/web/engine.go new file mode 100644 index 0000000..44196ab --- /dev/null +++ b/admin/lib/web/engine.go @@ -0,0 +1,34 @@ +package web + +import "github.com/gin-gonic/gin" + +type Engine struct { + *RoutesGroup + newContextFun func(ctx *gin.Context) IContext + rawEngine *gin.Engine +} + +func New(newContextFun func(ctx *gin.Context) IContext) *Engine { + rawE := gin.Default() + e := &Engine{ + RoutesGroup: newRoutesGroup(&rawE.RouterGroup, newContextFun), + newContextFun: newContextFun, + rawEngine: rawE, + } + + return e +} + +func (e *Engine) Use(middlewares ...HandlerFunc) { + e.rawEngine.Use(getGinHandlerFunWithRequest(e.newContextFun, middlewares...)...) +} + +func (e *Engine) Run(addr string) error { + return e.rawEngine.Run(addr) +} + +func (e *Engine) TravelPaths(travelFun func(path string, parentDesc string, method string, handlers ...HandlerFunc)) { + for _, c := range e.RoutesGroup.node.child { + c.travel("", "", travelFun) + } +} diff --git a/admin/lib/web/example/example.go b/admin/lib/web/example/example.go deleted file mode 100644 index 4d27ae7..0000000 --- a/admin/lib/web/example/example.go +++ /dev/null @@ -1,212 +0,0 @@ -package main - -import ( - "admin/lib/web" - "fmt" - "html/template" - "sort" -) - -type MyContext struct { - rawCtx web.RawContext -} - -func (ctx *MyContext) SetRawContext(rawCtx web.RawContext) { - ctx.rawCtx = rawCtx -} -func (ctx *MyContext) GetRawContext() web.RawContext { - return ctx.rawCtx -} - -func main() { - coreRouter := "iris" // gin|iris - engine := web.NewEngine(":8888", coreRouter, func() web.Context { - return new(MyContext) - }) - groupV1 := engine.Group("/v1") - { - type Test1 struct { - RoleId string `json:"role_id" desc:"角色id字段" required:"true"` - F1 int `json:"f1" desc:"这是字段1" default:"324"` - F2 string `json:"f2" desc:"这是字段2" default:"abcd"` - F3 bool `json:"f3" desc:"这是字段3" default:"false"` - } - groupV1.Get("/test1", "设置玩家背包数据", web.AccessMode_Write, Test1{}, func(ctx *MyContext, params *Test1) { - fmt.Printf("receive test1 path params:%+v\n", params) - ctx.GetRawContext().Json(200, map[string]any{ - "msg": "ok", - "code": 200, - }) - }) - groupV1.Post("/test1", "获取玩家数据", web.AccessMode_Read, Test1{}, func(ctx *MyContext, params *Test1) { - fmt.Printf("receive test1 path params:%+v\n", params) - ctx.GetRawContext().Json(200, map[string]any{ - "msg": "ok", - "code": 200, - }) - }) - // URI --> :8888/v1/test1?f1=123&f2=sdfsd&f3=true - // BODY --> :8888/v1/test1 {"f1":123,"f2":"sdfds","f3":"true"} - } - engine.Get("/test2", "获取玩家比赛", web.AccessMode_Read, nil, func(ctx *MyContext) { - fmt.Printf("receive test2 request\n") - ctx.GetRawContext().Json(200, map[string]any{ - "msg": "ok", - "code": 200, - }) - }) - engine.Post("/test2", "测试gm指令名字", web.AccessMode_Read, nil, func(ctx *MyContext) { - fmt.Printf("receive test2 request\n") - ctx.GetRawContext().Json(200, map[string]any{ - "msg": "ok", - "code": 200, - }) - }) - groupV2 := engine.Group("v2") - { - type Test2 struct { - F1 int `json:"f1" desc:"这是字段1"` - F2 string `json:"f2" desc:"这是字段2"` - F3 bool `json:"f3" desc:"这是字段3"` - } - groupV2.Post("test3", "测试gm指令名字123", web.AccessMode_Write, Test2{}, func(ctx *MyContext, params *Test2) { - fmt.Printf("receive test3\n") - ctx.GetRawContext().Json(200, map[string]any{ - "msg": "ok", - "code": 200, - }) - }) - } - - engine.Get("path_tree", "测试gm指令名字3424", web.AccessMode_Write, nil, func(ctx *MyContext) { - tree := engine.TravelPathTree() - ctx.GetRawContext().Json(200, tree) - }) - - engine.Get("/grid", "获取指令描述表", web.AccessMode_Read, nil, func(c *MyContext) { - tree := &Tree{tree: engine.TravelPathTree()} - - tmpl, err := template.New("html_test").Funcs(template.FuncMap(map[string]any{ - "incr": incr, - })).Parse(tplText) - if err != nil { - panic(err) - } - err = tmpl.Execute(c.GetRawContext().Writer(), tree) - if err != nil { - panic(err) - } - }) - - err := engine.Run() - if err != nil { - panic(err) - } -} - -type Path struct { - Path string - Route *web.RouteDescInfo -} - -type Tree struct { - tree map[string]*web.RouteDescInfo -} - -func (t *Tree) Paths() [][]*Path { - splitCol := 4 - list := make([]*Path, 0) - for k, v := range t.tree { - list = append(list, &Path{Path: k, Route: v}) - } - sort.SliceStable(list, func(i, j int) bool { - return list[i].Path < list[j].Path - }) - - if len(list) <= splitCol { - return [][]*Path{list} - } - - section := len(list) / splitCol - paths := make([][]*Path, splitCol) - - for i := 0; i < splitCol; i++ { - paths[i] = make([]*Path, 0) - start := i * section - for j := 0; j < section; j++ { - start += j - paths[i] = append(paths[i], list[start]) - } - } - - if len(list)%splitCol > 0 { - idx := 0 - for i := len(list) - len(list)%splitCol; i < len(list); i++ { - paths[idx] = append(paths[idx], list[i]) - idx++ - } - } - - return paths -} - -func incr(src int) int { - return src + 1 -} - -var tplText = ` - - -
- -{{ $path.Route.Desc }} | -|||||
---|---|---|---|---|---|
请求路径 | -{{ $path.Path }} | -||||
方法 | -{{ $path.Route.MethodDesc "或" }} | -||||
{{ printf "参数%d" $idx1 }} | -{{printf "%s" $field.Name }} | -{{printf "%s" $field.Type }} | -{{printf "%s" $field.Desc }} | - {{ if eq $field.Default "" }} -{{printf "默认:无" }} | - {{ else }} -{{printf "默认:%s" $field.Default }} | - {{ end }} -
无需参数 | - {{ end }} - - {{ end }} -