optimize
This commit is contained in:
parent
dafa58a5d0
commit
f815590b7c
@ -8,14 +8,14 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func initFun(app *node.Application) error {
|
func initFun(app *node.Application) error {
|
||||||
svc := service.NewCmdServerSvc(global.GLOB_DB) // 初始化应用服务
|
svc := service.New(global.GLOB_DB) // 初始化应用服务
|
||||||
srv := server.New(svc) // 初始化http服务
|
srv := server.New(svc) // 初始化http服务
|
||||||
srv.Route(global.GLOB_API_ENGINE) // 初始化http服务路由
|
srv.Route(global.GLOB_API_ENGINE) // 初始化http服务路由
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func New() *node.ApplicationDescInfo {
|
func New() *node.ApplicationDescInfo {
|
||||||
app := node.NewApplicationDescInfo("user", initFun)
|
app := node.NewApplicationDescInfo("game", initFun)
|
||||||
return app
|
return app
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ package entity
|
|||||||
import (
|
import (
|
||||||
"admin/apps/game/model"
|
"admin/apps/game/model"
|
||||||
"admin/apps/game/model/dto"
|
"admin/apps/game/model/dto"
|
||||||
|
"math/rand"
|
||||||
"reflect"
|
"reflect"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -31,13 +32,17 @@ func FromProjectDto(dto dto.CommonDtoValues) *Project {
|
|||||||
po := et.po
|
po := et.po
|
||||||
|
|
||||||
//to := reflect.TypeOf(po)
|
//to := reflect.TypeOf(po)
|
||||||
vo := reflect.ValueOf(po)
|
vo := reflect.ValueOf(po).Elem()
|
||||||
|
to := reflect.TypeOf(po).Elem()
|
||||||
|
|
||||||
for k, v := range dto {
|
for k, v := range dto {
|
||||||
fo := vo.FieldByName(k)
|
fo := vo.FieldByName(k)
|
||||||
fo.Set(reflect.ValueOf(v))
|
ft, _ := to.FieldByName(k)
|
||||||
|
fo.Set(parseStr2FieldValue(ft, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
et.Id = po.ID
|
||||||
|
|
||||||
return et
|
return et
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,7 +82,7 @@ func (et *Project) GetDtoFieldsDescInfo() []*dto.CommonDtoFieldDesc {
|
|||||||
Type: ft.Type.Name(),
|
Type: ft.Type.Name(),
|
||||||
HelpText: ft.Tag.Get("desc"),
|
HelpText: ft.Tag.Get("desc"),
|
||||||
Editable: true,
|
Editable: true,
|
||||||
Require: true,
|
Require: rand.Int()%2 == 0,
|
||||||
Choices: make([]*dto.CommonDtoFieldChoice, 0),
|
Choices: make([]*dto.CommonDtoFieldChoice, 0),
|
||||||
MultiChoice: false,
|
MultiChoice: false,
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,8 @@ func FromServerDto(dto dto.CommonDtoValues) *Server {
|
|||||||
fo.Set(reflect.ValueOf(v))
|
fo.Set(reflect.ValueOf(v))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
et.Id = po.ID
|
||||||
|
|
||||||
return et
|
return et
|
||||||
}
|
}
|
||||||
|
|
||||||
|
68
admin/apps/game/domain/entity/utils.go
Normal file
68
admin/apps/game/domain/entity/utils.go
Normal file
@ -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)
|
||||||
|
}
|
@ -34,12 +34,12 @@ func (repo *projectRepoImpl) List(pageNo, pageLen int) ([]*entity.Project, error
|
|||||||
}
|
}
|
||||||
|
|
||||||
// debug
|
// debug
|
||||||
list = append(list, &model.Project{
|
//list = append(list, &model.Project{
|
||||||
ID: 123,
|
// ID: 123,
|
||||||
Name: "神魔大陆",
|
// Name: "神魔大陆",
|
||||||
Desc: "神魔大陆服务器",
|
// Desc: "神魔大陆服务器",
|
||||||
ApiAddr: "http://192.168.1.1:8081",
|
// ApiAddr: "http://192.168.1.1:8081",
|
||||||
})
|
//})
|
||||||
|
|
||||||
entityList := make([]*entity.Project, 0, len(list))
|
entityList := make([]*entity.Project, 0, len(list))
|
||||||
for _, Project := range list {
|
for _, Project := range list {
|
||||||
|
@ -31,3 +31,8 @@ type CommonDtoList struct {
|
|||||||
FieldsDesc []*CommonDtoFieldDesc `json:"fields_desc"` // 数据字段描述信息
|
FieldsDesc []*CommonDtoFieldDesc `json:"fields_desc"` // 数据字段描述信息
|
||||||
Rows []CommonDtoValues `json:"rows"` // 数据行
|
Rows []CommonDtoValues `json:"rows"` // 数据行
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PathInfo struct {
|
||||||
|
Path string `json:"path"`
|
||||||
|
Method string `json:"method"`
|
||||||
|
}
|
||||||
|
45
admin/apps/game/model/dto/msg.go
Normal file
45
admin/apps/game/model/dto/msg.go
Normal file
@ -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"`
|
||||||
|
}
|
@ -1,3 +0,0 @@
|
|||||||
package dto
|
|
||||||
|
|
||||||
type CommonListRsp = CommonDtoList
|
|
@ -5,38 +5,37 @@ import (
|
|||||||
"admin/internal/context"
|
"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)
|
list, err := ctl.svc.CommonList(ctx, restfulResourceName, params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Fail(err)
|
return err
|
||||||
return
|
|
||||||
}
|
}
|
||||||
ctx.Ok(list)
|
*rsp = *list
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ctl *controller) CommonPost(ctx *context.WebContext, restfulResourceName string, params *dto.CommonDtoValues) {
|
func (ctl *controller) CommonPost(ctx *context.WebContext, restfulResourceName string, params *dto.CommonPostReq, rsp *dto.CommonPostRsp) error {
|
||||||
newObj, err := ctl.svc.CommonPost(ctx, restfulResourceName, *params)
|
newObj, err := ctl.svc.CommonPost(ctx, restfulResourceName, *params.Dto)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Fail(err)
|
return err
|
||||||
return
|
|
||||||
}
|
}
|
||||||
ctx.Ok(newObj)
|
rsp.Dto = &newObj
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ctl *controller) CommonPut(ctx *context.WebContext, restfulResourceName string, params *dto.CommonDtoValues) {
|
func (ctl *controller) CommonPut(ctx *context.WebContext, restfulResourceName string, params *dto.CommonPutReq, rsp *dto.CommonPutRsp) error {
|
||||||
newObj, err := ctl.svc.CommonPut(ctx, restfulResourceName, *params)
|
newObj, err := ctl.svc.CommonPut(ctx, restfulResourceName, *params.Dto)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Fail(err)
|
return err
|
||||||
return
|
|
||||||
}
|
}
|
||||||
ctx.Ok(newObj)
|
rsp.Dto = &newObj
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ctl *controller) CommonDelete(ctx *context.WebContext, restfulResourceName string, id int) {
|
func (ctl *controller) CommonDelete(ctx *context.WebContext, restfulResourceName string, params *dto.CommonDeleteReq, rsp *dto.CommonDeleteRsp) error {
|
||||||
err := ctl.svc.CommonDelete(ctx, restfulResourceName, id)
|
err := ctl.svc.CommonDelete(ctx, restfulResourceName, params.Id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Fail(err)
|
return err
|
||||||
return
|
|
||||||
}
|
}
|
||||||
ctx.Ok(nil)
|
return nil
|
||||||
}
|
}
|
||||||
|
31
admin/apps/game/server/ctl_game.go
Normal file
31
admin/apps/game/server/ctl_game.go
Normal file
@ -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() {
|
||||||
|
|
||||||
|
}
|
@ -3,55 +3,57 @@ package server
|
|||||||
import (
|
import (
|
||||||
"admin/apps/game/model/dto"
|
"admin/apps/game/model/dto"
|
||||||
"admin/internal/context"
|
"admin/internal/context"
|
||||||
|
"admin/internal/global"
|
||||||
"admin/lib/web"
|
"admin/lib/web"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (srv *Server) Route(engine *web.Engine) {
|
func (srv *Server) Route(engine *web.Engine) {
|
||||||
apiGroup := engine.Group("/api")
|
apiGroup := engine.Group("/api", "")
|
||||||
srv.proRoute(apiGroup)
|
srv.proRoute(apiGroup)
|
||||||
srv.serverRoute(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"
|
resourceName := "project"
|
||||||
proGroup := engine.Group("/" + resourceName)
|
srv.registerResourceRouter(resourceName, 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))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (srv *Server) serverRoute(engine *web.Group) {
|
func (srv *Server) serverRoute(engine *web.RoutesGroup) {
|
||||||
resourceName := "server"
|
resourceName := "server"
|
||||||
proGroup := engine.Group("/" + resourceName)
|
srv.registerResourceRouter(resourceName, 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))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func commonHandlerList(ctl *controller, resourceName string) func(ctx *context.WebContext, params *dto.CommonListReq) {
|
func (srv *Server) registerResourceRouter(resourceName string, group *web.RoutesGroup) {
|
||||||
return func(ctx *context.WebContext, params *dto.CommonListReq) {
|
group.Get("", "获取列表", global.WebPathPermit_Read, commonHandlerList(srv.ctl, resourceName))
|
||||||
ctl.CommonList(ctx, resourceName, params)
|
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) {
|
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) {
|
return func(ctx *context.WebContext, params *dto.CommonPostReq, rsp *dto.CommonPostRsp) error {
|
||||||
ctl.CommonPost(ctx, resourceName, params.Dto)
|
return ctl.CommonPost(ctx, resourceName, params, rsp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func commonHandlerPut(ctl *controller, resourceName string) func(ctx *context.WebContext, params *dto.CommonPutReq) {
|
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) {
|
return func(ctx *context.WebContext, params *dto.CommonPutReq, rsp *dto.CommonPutRsp) error {
|
||||||
ctl.CommonPut(ctx, resourceName, params.Dto)
|
return ctl.CommonPut(ctx, resourceName, params, rsp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func commonHandlerDelete(ctl *controller, resourceName string) func(ctx *context.WebContext, params *dto.CommonDeleteReq) {
|
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) {
|
return func(ctx *context.WebContext, params *dto.CommonDeleteReq, rsp *dto.CommonDeleteRsp) error {
|
||||||
ctl.CommonDelete(ctx, resourceName, params.Id)
|
return ctl.CommonDelete(ctx, resourceName, params, rsp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ type Service struct {
|
|||||||
serverSvc *domain.ServerSvc
|
serverSvc *domain.ServerSvc
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewCmdServerSvc(db *gorm.DB) *Service {
|
func New(db *gorm.DB) *Service {
|
||||||
return &Service{
|
return &Service{
|
||||||
db: db,
|
db: db,
|
||||||
projectSvc: domain.NewProjectSvc(db),
|
projectSvc: domain.NewProjectSvc(db),
|
||||||
|
28
admin/apps/mockpro/boot.go
Normal file
28
admin/apps/mockpro/boot.go
Normal file
@ -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)
|
||||||
|
}
|
||||||
|
}
|
48
admin/apps/mockpro/domain/ban.go
Normal file
48
admin/apps/mockpro/domain/ban.go
Normal file
@ -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)
|
||||||
|
}
|
89
admin/apps/mockpro/domain/entity/server.go
Normal file
89
admin/apps/mockpro/domain/entity/server.go
Normal file
@ -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
|
||||||
|
}
|
89
admin/apps/mockpro/domain/entity/whitelist.go
Normal file
89
admin/apps/mockpro/domain/entity/whitelist.go
Normal file
@ -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
|
||||||
|
}
|
31
admin/apps/mockpro/domain/irestfull.go
Normal file
31
admin/apps/mockpro/domain/irestfull.go
Normal file
@ -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
|
||||||
|
}
|
69
admin/apps/mockpro/domain/repo/ban.go
Normal file
69
admin/apps/mockpro/domain/repo/ban.go
Normal file
@ -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
|
||||||
|
}
|
69
admin/apps/mockpro/domain/repo/whitelist.go
Normal file
69
admin/apps/mockpro/domain/repo/whitelist.go
Normal file
@ -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
|
||||||
|
}
|
48
admin/apps/mockpro/domain/whitelist.go
Normal file
48
admin/apps/mockpro/domain/whitelist.go
Normal file
@ -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)
|
||||||
|
}
|
5
admin/apps/mockpro/internal/config/flags.go
Normal file
5
admin/apps/mockpro/internal/config/flags.go
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
type MockBootFlags struct {
|
||||||
|
ApiPort string `env:"mock_api_port" default:"8654" desc:"api端口,客户端请求的地址端口"`
|
||||||
|
}
|
11
admin/apps/mockpro/internal/global/var.go
Normal file
11
admin/apps/mockpro/internal/global/var.go
Normal file
@ -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
|
||||||
|
)
|
20
admin/apps/mockpro/internal/model/account.go
Normal file
20
admin/apps/mockpro/internal/model/account.go
Normal file
@ -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"`
|
||||||
|
}
|
22
admin/apps/mockpro/internal/model/ban.go
Normal file
22
admin/apps/mockpro/internal/model/ban.go
Normal file
@ -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"`
|
||||||
|
}
|
22
admin/apps/mockpro/internal/model/devicepush.go
Normal file
22
admin/apps/mockpro/internal/model/devicepush.go
Normal file
@ -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"`
|
||||||
|
}
|
33
admin/apps/mockpro/internal/model/dto/common.go
Normal file
33
admin/apps/mockpro/internal/model/dto/common.go
Normal file
@ -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"` // 数据行
|
||||||
|
}
|
@ -1,5 +1,11 @@
|
|||||||
package dto
|
package dto
|
||||||
|
|
||||||
|
type NilReq struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
type NilRsp struct {
|
||||||
|
}
|
||||||
|
|
||||||
type CommonListReq struct {
|
type CommonListReq struct {
|
||||||
PageNo int `json:"page_no"`
|
PageNo int `json:"page_no"`
|
||||||
PageLen int `json:"page_len"`
|
PageLen int `json:"page_len"`
|
||||||
@ -16,3 +22,17 @@ type CommonPutReq struct {
|
|||||||
type CommonDeleteReq struct {
|
type CommonDeleteReq struct {
|
||||||
Id int `json:"id"`
|
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"`
|
||||||
|
}
|
23
admin/apps/mockpro/internal/model/globalmail.go
Normal file
23
admin/apps/mockpro/internal/model/globalmail.go
Normal file
@ -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"`
|
||||||
|
}
|
23
admin/apps/mockpro/internal/model/notice.go
Normal file
23
admin/apps/mockpro/internal/model/notice.go
Normal file
@ -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"`
|
||||||
|
}
|
24
admin/apps/mockpro/internal/model/order.go
Normal file
24
admin/apps/mockpro/internal/model/order.go
Normal file
@ -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"`
|
||||||
|
}
|
21
admin/apps/mockpro/internal/model/rewardcode.go
Normal file
21
admin/apps/mockpro/internal/model/rewardcode.go
Normal file
@ -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"`
|
||||||
|
}
|
22
admin/apps/mockpro/internal/model/role.go
Normal file
22
admin/apps/mockpro/internal/model/role.go
Normal file
@ -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"`
|
||||||
|
}
|
30
admin/apps/mockpro/internal/model/rolemail.go
Normal file
30
admin/apps/mockpro/internal/model/rolemail.go
Normal file
@ -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"`
|
||||||
|
}
|
22
admin/apps/mockpro/internal/model/whitelist.go
Normal file
22
admin/apps/mockpro/internal/model/whitelist.go
Normal file
@ -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"`
|
||||||
|
}
|
11
admin/apps/mockpro/server/ctl.go
Normal file
11
admin/apps/mockpro/server/ctl.go
Normal file
@ -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}
|
||||||
|
}
|
40
admin/apps/mockpro/server/ctl_mock.go
Normal file
40
admin/apps/mockpro/server/ctl_mock.go
Normal file
@ -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
|
||||||
|
}
|
43
admin/apps/mockpro/server/ctx_web.go
Normal file
43
admin/apps/mockpro/server/ctx_web.go
Normal file
@ -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)
|
||||||
|
}
|
105
admin/apps/mockpro/server/route.go
Normal file
105
admin/apps/mockpro/server/route.go
Normal file
@ -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)
|
||||||
|
}
|
||||||
|
}
|
48
admin/apps/mockpro/server/route_desc.go
Normal file
48
admin/apps/mockpro/server/route_desc.go
Normal file
@ -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
|
||||||
|
}
|
29
admin/apps/mockpro/server/server.go
Normal file
29
admin/apps/mockpro/server/server.go
Normal file
@ -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
|
||||||
|
}
|
68
admin/apps/mockpro/service/service.go
Normal file
68
admin/apps/mockpro/service/service.go
Normal file
@ -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)
|
||||||
|
}
|
@ -2,6 +2,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"admin/apps/game"
|
"admin/apps/game"
|
||||||
|
"admin/apps/mockpro"
|
||||||
"admin/internal/mynode"
|
"admin/internal/mynode"
|
||||||
"admin/lib/node"
|
"admin/lib/node"
|
||||||
)
|
)
|
||||||
@ -11,6 +12,7 @@ var appList []*node.ApplicationDescInfo
|
|||||||
func init() {
|
func init() {
|
||||||
appList = []*node.ApplicationDescInfo{
|
appList = []*node.ApplicationDescInfo{
|
||||||
game.New(),
|
game.New(),
|
||||||
|
mockpro.New(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,41 +3,55 @@ package context
|
|||||||
import (
|
import (
|
||||||
"admin/internal/errcode"
|
"admin/internal/errcode"
|
||||||
"admin/lib/web"
|
"admin/lib/web"
|
||||||
|
"admin/lib/xlog"
|
||||||
"context"
|
"context"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
type WebContext struct {
|
type WebContext struct {
|
||||||
context.Context
|
context.Context
|
||||||
rawCtx web.RawContext
|
rawCtx *gin.Context
|
||||||
|
alreadySetRsp bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewWebContext() web.Context {
|
func NewWebContext(rawCtx *gin.Context) web.IContext {
|
||||||
return &WebContext{}
|
return &WebContext{rawCtx: rawCtx}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ctx *WebContext) Ok(data any) {
|
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,
|
"code": 200,
|
||||||
"msg": "",
|
"msg": "",
|
||||||
"data": data,
|
"data": data,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
ctx.alreadySetRsp = true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ctx *WebContext) Fail(err error) {
|
func (ctx *WebContext) Fail(err error) {
|
||||||
|
if ctx.alreadySetRsp {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
code, stack, msg := errcode.ParseError(err)
|
code, stack, msg := errcode.ParseError(err)
|
||||||
ctx.rawCtx.Json(200, map[string]any{
|
ctx.rawCtx.JSON(200, map[string]any{
|
||||||
"code": code,
|
"code": code,
|
||||||
"stack": stack,
|
"stack": stack,
|
||||||
"msg": msg,
|
"msg": msg,
|
||||||
"data": "",
|
"data": "",
|
||||||
})
|
})
|
||||||
|
|
||||||
|
ctx.alreadySetRsp = true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ctx *WebContext) SetRawContext(rawCtx web.RawContext) {
|
func (ctx *WebContext) HandleError(path string, err error) {
|
||||||
ctx.Context = context.Background()
|
xlog.Errorf("path:%v handle error:%v ", path, err)
|
||||||
ctx.rawCtx = rawCtx
|
ctx.Fail(err)
|
||||||
}
|
}
|
||||||
|
func (ctx *WebContext) HandleSuccess(rspData any) {
|
||||||
func (ctx *WebContext) GetRawContext() web.RawContext {
|
ctx.Ok(rspData)
|
||||||
return ctx.rawCtx
|
|
||||||
}
|
}
|
||||||
|
@ -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)
|
db.Raw("SELECT COUNT(*) FROM information_schema.schemata WHERE schema_name = ?", dbName).Scan(&count)
|
||||||
if count == 0 {
|
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)
|
dbName)
|
||||||
if e := db.Exec(sql).Error; e != nil {
|
if e := db.Exec(sql).Error; e != nil {
|
||||||
return "", fmt.Errorf("failed to create database:%v", e)
|
return "", fmt.Errorf("failed to create database:%v", e)
|
||||||
|
6
admin/internal/global/consts.go
Normal file
6
admin/internal/global/consts.go
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
package global
|
||||||
|
|
||||||
|
const (
|
||||||
|
WebPathPermit_Read = 1
|
||||||
|
WebPathPermit_Write = 2
|
||||||
|
)
|
@ -14,7 +14,7 @@ func New() *node.Node {
|
|||||||
nd.ApplyOptions(node.WithNodeExBootFlags(global.GLOB_BOOT_FLAGS))
|
nd.ApplyOptions(node.WithNodeExBootFlags(global.GLOB_BOOT_FLAGS))
|
||||||
|
|
||||||
nd.AddInitTask("初始化全局api监听服务", func() error {
|
nd.AddInitTask("初始化全局api监听服务", func() error {
|
||||||
global.GLOB_API_ENGINE = web.NewEngine("gin", context.NewWebContext)
|
global.GLOB_API_ENGINE = web.New(context.NewWebContext)
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
|
73
admin/lib/httpclient/client.go
Normal file
73
admin/lib/httpclient/client.go
Normal file
@ -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
|
||||||
|
}
|
||||||
|
}
|
@ -112,7 +112,7 @@ func (node *Node) initBootConfig() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (node *Node) initLog() error {
|
func (node *Node) initLog() error {
|
||||||
logConfig := &LogBootConfig{}
|
logConfig := DefaultLogBootConfig()
|
||||||
if node.bootConfigFile.globalBootConfigFileContent != nil {
|
if node.bootConfigFile.globalBootConfigFileContent != nil {
|
||||||
logConfig = node.bootConfigFile.globalBootConfigFileContent.GetLogConfig().Check()
|
logConfig = node.bootConfigFile.globalBootConfigFileContent.GetLogConfig().Check()
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,12 @@ type LogBootConfig struct {
|
|||||||
LogLevel string `yaml:"log_level"` // 日志等级: trace/debug/info/notice/warn/error/fatal
|
LogLevel string `yaml:"log_level"` // 日志等级: trace/debug/info/notice/warn/error/fatal
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func DefaultLogBootConfig() *LogBootConfig {
|
||||||
|
return &LogBootConfig{
|
||||||
|
LogLevel: "trace",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (lc *LogBootConfig) Check() *LogBootConfig {
|
func (lc *LogBootConfig) Check() *LogBootConfig {
|
||||||
if lc.LogDir == "" {
|
if lc.LogDir == "" {
|
||||||
lc.LogDir = "./logs"
|
lc.LogDir = "./logs"
|
||||||
|
57
admin/lib/web/desc.go
Normal file
57
admin/lib/web/desc.go
Normal file
@ -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)
|
||||||
|
}
|
||||||
|
}
|
34
admin/lib/web/engine.go
Normal file
34
admin/lib/web/engine.go
Normal file
@ -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)
|
||||||
|
}
|
||||||
|
}
|
@ -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 = `
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<title>GM MASTER</title>
|
|
||||||
<div style="padding-left: 50px;">
|
|
||||||
{{ $pathsList := .Paths }}
|
|
||||||
{{ range $pidex, $paths := $pathsList }}
|
|
||||||
<div style="float:left">
|
|
||||||
<h1 style="text-align: center">指令列表{{ incr $pidex }}</h1>
|
|
||||||
<div style="padding-left: 20px;padding-right: 20px">
|
|
||||||
<table border = "1" align="center">
|
|
||||||
{{ range $idx, $path := $paths }}
|
|
||||||
<tr>
|
|
||||||
<th colspan="5" style="background-color: green; text-align: left">{{ $path.Route.Desc }}</th>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><b>请求路径</b></td>
|
|
||||||
<th colspan="4" style="text-align: left"> {{ $path.Path }}</th>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><b>方法</b></td>
|
|
||||||
<th colspan="4" style="text-align: left"> {{ $path.Route.MethodDesc "或" }}</th>
|
|
||||||
</tr>
|
|
||||||
{{ if $path.Route.HasRequest }}
|
|
||||||
{{ range $idx1, $field := $path.Route.Fields }}
|
|
||||||
<tr>
|
|
||||||
<td><b>{{ printf "参数%d" $idx1 }}</b></td>
|
|
||||||
<td style="text-align: center">{{printf "%s" $field.Name }}</td>
|
|
||||||
<td style="text-align: center">{{printf "%s" $field.Type }}</td>
|
|
||||||
<td>{{printf "%s" $field.Desc }}</td>
|
|
||||||
{{ if eq $field.Default "" }}
|
|
||||||
<td>{{printf "默认:无" }}</td>
|
|
||||||
{{ else }}
|
|
||||||
<td>{{printf "默认:%s" $field.Default }}</td>
|
|
||||||
{{ end }}
|
|
||||||
</tr>
|
|
||||||
{{ end }}
|
|
||||||
{{ else }}
|
|
||||||
<tr><th colspan="5">无需参数</th>
|
|
||||||
{{ end }}
|
|
||||||
<!--<tr><th colspan="5"><hr></th></tr>-->
|
|
||||||
{{ end }}
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{{ end }}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
`
|
|
1
admin/lib/web/example/main.go
Normal file
1
admin/lib/web/example/main.go
Normal file
@ -0,0 +1 @@
|
|||||||
|
package example
|
@ -1,183 +0,0 @@
|
|||||||
package web
|
|
||||||
|
|
||||||
type routeGroupInterface interface {
|
|
||||||
Use(middlewares ...HandlerFunc)
|
|
||||||
Group(path string, handlers ...HandlerFunc) routeGroupInterface
|
|
||||||
Get(path string, desc string, req any, handlers ...HandlerFunc) routeGroupInterface
|
|
||||||
Post(path string, desc string, req any, handlers ...HandlerFunc) routeGroupInterface
|
|
||||||
Put(path string, desc string, req any, handlers ...HandlerFunc) routeGroupInterface
|
|
||||||
Delete(path string, desc string, req any, handlers ...HandlerFunc) routeGroupInterface
|
|
||||||
}
|
|
||||||
|
|
||||||
type Group struct {
|
|
||||||
coreRouter routeGroupInterface
|
|
||||||
DirectRoutes map[string]*RouteDescInfo
|
|
||||||
GroupRoutes map[string]*Group
|
|
||||||
}
|
|
||||||
|
|
||||||
func newGroup(coreRouter routeGroupInterface) *Group {
|
|
||||||
g := &Group{
|
|
||||||
coreRouter: coreRouter,
|
|
||||||
DirectRoutes: make(map[string]*RouteDescInfo),
|
|
||||||
GroupRoutes: make(map[string]*Group),
|
|
||||||
}
|
|
||||||
return g
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Group) Use(middlewares ...HandlerFunc) {
|
|
||||||
e.coreRouter.Use(middlewares...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Group) Group(path string, handlers ...HandlerFunc) *Group {
|
|
||||||
path = pathBeTheSame(path)
|
|
||||||
routeGroup := e.coreRouter.Group(path, handlers...)
|
|
||||||
group := newGroup(routeGroup)
|
|
||||||
e.GroupRoutes[path] = group
|
|
||||||
return group
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get 注册get方法路由,根据request请求体优先从body中以json格式解析参数,如果没有body,则从uri参数中解析出请求参数
|
|
||||||
//
|
|
||||||
// path:路径
|
|
||||||
// desc:路由的一个简短描述
|
|
||||||
// request:请求结构体
|
|
||||||
// 格式:
|
|
||||||
// type struct {
|
|
||||||
// F1 int `json:"f1" desc:"字段描述" default:"234" required:"true"`
|
|
||||||
// }
|
|
||||||
// tag描述:
|
|
||||||
// json:字段名
|
|
||||||
// desc:字段简短描述,没有可以不写
|
|
||||||
// default:默认值,没有可以不写
|
|
||||||
// required:是否必填字段,没有要求可以不写
|
|
||||||
// 注意,get、post注册的request结构字段,如果是uri参数方式类型只支持golang基础类型以及基础类型的切片,不能是结构体类型,
|
|
||||||
// 例如:
|
|
||||||
// type Field struct {
|
|
||||||
// A int
|
|
||||||
// B bool
|
|
||||||
// }
|
|
||||||
// type Request struct {
|
|
||||||
// F1 *Field
|
|
||||||
// }
|
|
||||||
// F1字段就是非法的,无法解析,会报错
|
|
||||||
// handlers:路由处理函数,如果没有请求体,就是func(ctx),否则就是func(ctx, request)
|
|
||||||
func (e *Group) Get(path string, desc string, access AccessMode, request any, handler HandlerFunc) {
|
|
||||||
path = pathBeTheSame(path)
|
|
||||||
old, find := e.DirectRoutes[path]
|
|
||||||
if !find {
|
|
||||||
e.DirectRoutes[path] = newRouteDescInfo(path, desc, "GET", access, request)
|
|
||||||
} else {
|
|
||||||
old.Method = append(old.Method, "GET")
|
|
||||||
e.DirectRoutes[path] = old
|
|
||||||
}
|
|
||||||
e.coreRouter.Get(path, desc, request, handler)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Post 注册post方法路由,根据request请求体优先从body中以json格式解析参数,如果没有body,则从uri参数中解析出请求参数
|
|
||||||
//
|
|
||||||
// path:路径
|
|
||||||
// desc:路由的一个简短描述
|
|
||||||
// request:请求结构体
|
|
||||||
// 格式:
|
|
||||||
// type struct {
|
|
||||||
// F1 int `json:"f1" desc:"字段描述" default:"234" required:"true"`
|
|
||||||
// }
|
|
||||||
// tag描述:
|
|
||||||
// json:字段名
|
|
||||||
// desc:字段简短描述,没有可以不写
|
|
||||||
// default:默认值,没有可以不写
|
|
||||||
// required:是否必填字段,没有要求可以不写
|
|
||||||
// 注意,get、post注册的request结构字段,如果是uri参数方式类型只支持golang基础类型以及基础类型的切片,不能是结构体类型,
|
|
||||||
// 例如:
|
|
||||||
// type Field struct {
|
|
||||||
// A int
|
|
||||||
// B bool
|
|
||||||
// }
|
|
||||||
// type Request struct {
|
|
||||||
// F1 *Field
|
|
||||||
// }
|
|
||||||
// F1字段就是非法的,无法解析,会报错
|
|
||||||
// handlers:路由处理函数,如果没有请求体,就是func(ctx),否则就是func(ctx, request)
|
|
||||||
func (e *Group) Post(path, desc string, access AccessMode, request any, handler HandlerFunc) {
|
|
||||||
path = pathBeTheSame(path)
|
|
||||||
old, find := e.DirectRoutes[path]
|
|
||||||
if !find {
|
|
||||||
e.DirectRoutes[path] = newRouteDescInfo(path, desc, "POST", access, request)
|
|
||||||
} else {
|
|
||||||
old.Method = append(old.Method, "POST")
|
|
||||||
e.DirectRoutes[path] = old
|
|
||||||
}
|
|
||||||
e.coreRouter.Post(path, desc, request, handler)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Group) Put(path, desc string, access AccessMode, request any, handler HandlerFunc) {
|
|
||||||
path = pathBeTheSame(path)
|
|
||||||
old, find := e.DirectRoutes[path]
|
|
||||||
if !find {
|
|
||||||
e.DirectRoutes[path] = newRouteDescInfo(path, desc, "PUT", access, request)
|
|
||||||
} else {
|
|
||||||
old.Method = append(old.Method, "PUT")
|
|
||||||
e.DirectRoutes[path] = old
|
|
||||||
}
|
|
||||||
e.coreRouter.Put(path, desc, request, handler)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Group) Delete(path, desc string, access AccessMode, request any, handler HandlerFunc) {
|
|
||||||
path = pathBeTheSame(path)
|
|
||||||
old, find := e.DirectRoutes[path]
|
|
||||||
if !find {
|
|
||||||
e.DirectRoutes[path] = newRouteDescInfo(path, desc, "DELETE", access, request)
|
|
||||||
} else {
|
|
||||||
old.Method = append(old.Method, "DELETE")
|
|
||||||
e.DirectRoutes[path] = old
|
|
||||||
}
|
|
||||||
e.coreRouter.Delete(path, desc, request, handler)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetAndPost 注册get&post方法路由,根据request请求体优先从body中以json格式解析参数,如果没有body,则从uri参数中解析出请求参数
|
|
||||||
//
|
|
||||||
// path:路径
|
|
||||||
// desc:路由的一个简短描述
|
|
||||||
// request:请求结构体
|
|
||||||
// 格式:
|
|
||||||
// type struct {
|
|
||||||
// F1 int `json:"f1" desc:"字段描述" default:"234" required:"true"`
|
|
||||||
// }
|
|
||||||
// tag描述:
|
|
||||||
// json:字段名
|
|
||||||
// desc:字段简短描述,没有可以不写
|
|
||||||
// default:默认值,没有可以不写
|
|
||||||
// required:是否必填字段,没有要求可以不写
|
|
||||||
// 注意,get、post注册的request结构字段,如果是uri参数方式类型只支持golang基础类型以及基础类型的切片,不能是结构体类型,
|
|
||||||
// 例如:
|
|
||||||
// type Field struct {
|
|
||||||
// A int
|
|
||||||
// B bool
|
|
||||||
// }
|
|
||||||
// type Request struct {
|
|
||||||
// F1 *Field
|
|
||||||
// }
|
|
||||||
// F1字段就是非法的,无法解析,会报错
|
|
||||||
// handlers:路由处理函数,如果没有请求体,就是func(ctx),否则就是func(ctx, request)
|
|
||||||
func (e *Group) GetAndPost(path, desc string, access AccessMode, request any, handler HandlerFunc) {
|
|
||||||
path = pathBeTheSame(path)
|
|
||||||
record := newRouteDescInfo(path, desc, "GET", access, request)
|
|
||||||
record.Method = append(record.Method, "POST")
|
|
||||||
e.DirectRoutes[path] = record
|
|
||||||
e.coreRouter.Get(path, desc, request, handler)
|
|
||||||
e.coreRouter.Post(path, desc, request, handler)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Group) TravelPathTree() map[string]*RouteDescInfo {
|
|
||||||
m := make(map[string]*RouteDescInfo)
|
|
||||||
for k, route := range e.DirectRoutes {
|
|
||||||
m[k] = route
|
|
||||||
}
|
|
||||||
for k, subG := range e.GroupRoutes {
|
|
||||||
gm := subG.TravelPathTree()
|
|
||||||
for k1, v1 := range gm {
|
|
||||||
m[k+k1] = v1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return m
|
|
||||||
}
|
|
@ -1,24 +0,0 @@
|
|||||||
package web
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Context interface {
|
|
||||||
SetRawContext(ctx RawContext)
|
|
||||||
GetRawContext() RawContext
|
|
||||||
}
|
|
||||||
|
|
||||||
type HandlerFunc any
|
|
||||||
|
|
||||||
type RawContext interface {
|
|
||||||
Json(code int, v any)
|
|
||||||
Writer() io.Writer
|
|
||||||
}
|
|
||||||
|
|
||||||
var ParseParamsErrorHandler = func(ctx Context, path string, err error) {
|
|
||||||
ctx.GetRawContext().Json(501, map[string]interface{}{
|
|
||||||
"MSG": fmt.Sprintf("parse params error:%v", err),
|
|
||||||
})
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
注意,get、post注册的request结构字段,如果是uri参数方式类型只支持golang基础类型以及基础类型的切片,不能是结构体类型,
|
|
||||||
例如:
|
|
||||||
type Field struct {
|
|
||||||
A int
|
|
||||||
B bool
|
|
||||||
}
|
|
||||||
type Request struct {
|
|
||||||
F1 *Field
|
|
||||||
}
|
|
||||||
F1字段就是非法的,无法解析,会报错
|
|
@ -1,173 +0,0 @@
|
|||||||
package web
|
|
||||||
|
|
||||||
import "fmt"
|
|
||||||
|
|
||||||
type routerInterface interface {
|
|
||||||
routeGroupInterface
|
|
||||||
Run(addr string) error
|
|
||||||
}
|
|
||||||
|
|
||||||
type Engine struct {
|
|
||||||
Addr string
|
|
||||||
newContextFun func() Context
|
|
||||||
DirectRoutes map[string]*RouteDescInfo
|
|
||||||
GroupRoutes map[string]*Group
|
|
||||||
coreRouter routerInterface
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewEngine 使用gin或者iris创建web引擎,newContextFun为调用方需要实现的context初始化函数
|
|
||||||
// coreRouter指定不同web引擎,目前只支持gin
|
|
||||||
func NewEngine(coreRouter string, newContextFun func() Context) *Engine {
|
|
||||||
e := &Engine{
|
|
||||||
newContextFun: newContextFun,
|
|
||||||
DirectRoutes: make(map[string]*RouteDescInfo),
|
|
||||||
GroupRoutes: make(map[string]*Group),
|
|
||||||
}
|
|
||||||
switch coreRouter {
|
|
||||||
//case "iris":
|
|
||||||
// e.coreRouter = newRouterIris(newContextFun)
|
|
||||||
case "gin":
|
|
||||||
e.coreRouter = newRouterGin(newContextFun)
|
|
||||||
default:
|
|
||||||
panic(fmt.Errorf("NewEngine only support irir or gin, invalid type:%v", coreRouter))
|
|
||||||
}
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Engine) Use(middlewares ...HandlerFunc) {
|
|
||||||
e.coreRouter.Use(middlewares...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Engine) Group(path string, handlers ...HandlerFunc) *Group {
|
|
||||||
path = pathBeTheSame(path)
|
|
||||||
routeGroup := e.coreRouter.Group(path, handlers...)
|
|
||||||
group := newGroup(routeGroup)
|
|
||||||
e.GroupRoutes[path] = group
|
|
||||||
return group
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get 注册get方法路由,根据request请求体优先从body中以json格式解析参数,如果没有body,则从uri参数中解析出请求参数
|
|
||||||
//
|
|
||||||
// path:路径
|
|
||||||
// desc:路由的一个简短描述
|
|
||||||
// request:请求结构体
|
|
||||||
// 格式:
|
|
||||||
// type struct {
|
|
||||||
// F1 int `json:"f1" desc:"字段描述" default:"234" required:"true"`
|
|
||||||
// }
|
|
||||||
// tag描述:
|
|
||||||
// json:字段名
|
|
||||||
// desc:字段简短描述,没有可以不写
|
|
||||||
// default:默认值,没有可以不写
|
|
||||||
// required:是否必填字段,没有要求可以不写
|
|
||||||
// 注意,get、post注册的request结构字段,如果是uri参数方式类型只支持golang基础类型以及基础类型的切片,不能是结构体类型,
|
|
||||||
// 例如:
|
|
||||||
// type Field struct {
|
|
||||||
// A int
|
|
||||||
// B bool
|
|
||||||
// }
|
|
||||||
// type Request struct {
|
|
||||||
// F1 *Field
|
|
||||||
// }
|
|
||||||
// F1字段就是非法的,无法解析,会报错
|
|
||||||
// handlers:路由处理函数,如果没有请求体,就是func(ctx),否则就是func(ctx, request)
|
|
||||||
func (e *Engine) Get(path string, desc string, access AccessMode, request any, handler HandlerFunc) {
|
|
||||||
path = pathBeTheSame(path)
|
|
||||||
old, find := e.DirectRoutes[path]
|
|
||||||
if !find {
|
|
||||||
e.DirectRoutes[path] = newRouteDescInfo(path, desc, "GET", access, request)
|
|
||||||
} else {
|
|
||||||
old.Method = append(old.Method, "GET")
|
|
||||||
e.DirectRoutes[path] = old
|
|
||||||
}
|
|
||||||
e.coreRouter.Get(path, desc, request, handler)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Post 注册post方法路由,根据request请求体优先从body中以json格式解析参数,如果没有body,则从uri参数中解析出请求参数
|
|
||||||
//
|
|
||||||
// path:路径
|
|
||||||
// desc:路由的一个简短描述
|
|
||||||
// request:请求结构体
|
|
||||||
// 格式:
|
|
||||||
// type struct {
|
|
||||||
// F1 int `json:"f1" desc:"字段描述" default:"234" required:"true"`
|
|
||||||
// }
|
|
||||||
// tag描述:
|
|
||||||
// json:字段名
|
|
||||||
// desc:字段简短描述,没有可以不写
|
|
||||||
// default:默认值,没有可以不写
|
|
||||||
// required:是否必填字段,没有要求可以不写
|
|
||||||
// 注意,get、post注册的request结构字段,如果是uri参数方式类型只支持golang基础类型以及基础类型的切片,不能是结构体类型,
|
|
||||||
// 例如:
|
|
||||||
// type Field struct {
|
|
||||||
// A int
|
|
||||||
// B bool
|
|
||||||
// }
|
|
||||||
// type Request struct {
|
|
||||||
// F1 *Field
|
|
||||||
// }
|
|
||||||
// F1字段就是非法的,无法解析,会报错
|
|
||||||
// handlers:路由处理函数,如果没有请求体,就是func(ctx),否则就是func(ctx, request)
|
|
||||||
func (e *Engine) Post(path, desc string, access AccessMode, request any, handler HandlerFunc) {
|
|
||||||
path = pathBeTheSame(path)
|
|
||||||
old, find := e.DirectRoutes[path]
|
|
||||||
if !find {
|
|
||||||
e.DirectRoutes[path] = newRouteDescInfo(path, desc, "POST", access, request)
|
|
||||||
} else {
|
|
||||||
old.Method = append(old.Method, "POST")
|
|
||||||
e.DirectRoutes[path] = old
|
|
||||||
}
|
|
||||||
e.coreRouter.Post(path, desc, request, handler)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Engine) Run(addr string) error {
|
|
||||||
e.Addr = addr
|
|
||||||
return e.coreRouter.Run(addr)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TravelPathTree 获取所有路径的描述表
|
|
||||||
func (e *Engine) TravelPathTree() map[string]*RouteDescInfo {
|
|
||||||
m := make(map[string]*RouteDescInfo)
|
|
||||||
for k, route := range e.DirectRoutes {
|
|
||||||
m[k] = route
|
|
||||||
}
|
|
||||||
for k, subG := range e.GroupRoutes {
|
|
||||||
gm := subG.TravelPathTree()
|
|
||||||
for k1, v1 := range gm {
|
|
||||||
m[k+k1] = v1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
|
|
||||||
func pathBeTheSame(path string) string {
|
|
||||||
if path == "" {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
if path == "/" {
|
|
||||||
return path
|
|
||||||
}
|
|
||||||
if path[0] != '/' {
|
|
||||||
path = "/" + path
|
|
||||||
}
|
|
||||||
if path[len(path)-1] == '/' {
|
|
||||||
path = path[:len(path)-1]
|
|
||||||
}
|
|
||||||
return path
|
|
||||||
}
|
|
||||||
|
|
||||||
func pathBeTheSame1(path string) string {
|
|
||||||
if path == "" {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
if path == "/" {
|
|
||||||
return path
|
|
||||||
}
|
|
||||||
if path[0] != '/' {
|
|
||||||
path = "/" + path
|
|
||||||
}
|
|
||||||
if path[len(path)-1] == '/' {
|
|
||||||
path = path[:len(path)-1]
|
|
||||||
}
|
|
||||||
return path
|
|
||||||
}
|
|
@ -1,85 +0,0 @@
|
|||||||
package web
|
|
||||||
|
|
||||||
import (
|
|
||||||
"reflect"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
type AccessMode int
|
|
||||||
|
|
||||||
const (
|
|
||||||
AccessMode_Read = 1
|
|
||||||
AccessMode_Write = 2
|
|
||||||
)
|
|
||||||
|
|
||||||
type RouteDescInfo struct {
|
|
||||||
Path string
|
|
||||||
Desc string
|
|
||||||
Method []string
|
|
||||||
AccessMode
|
|
||||||
rawRequest any
|
|
||||||
Fields []*FieldDescInfo
|
|
||||||
}
|
|
||||||
|
|
||||||
func newRouteDescInfo(path, desc, method string, access AccessMode, request any) *RouteDescInfo {
|
|
||||||
info := &RouteDescInfo{
|
|
||||||
Path: path,
|
|
||||||
Desc: desc,
|
|
||||||
Method: []string{method},
|
|
||||||
AccessMode: access,
|
|
||||||
rawRequest: request,
|
|
||||||
}
|
|
||||||
info.RequestFieldsDesc()
|
|
||||||
return info
|
|
||||||
}
|
|
||||||
|
|
||||||
func (info *RouteDescInfo) MethodDesc(sep string) string {
|
|
||||||
return strings.Join(info.Method, sep)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (info *RouteDescInfo) RequestFieldsDesc() []*FieldDescInfo {
|
|
||||||
if !info.HasRequest() {
|
|
||||||
return []*FieldDescInfo{}
|
|
||||||
}
|
|
||||||
|
|
||||||
list := make([]*FieldDescInfo, 0)
|
|
||||||
to := reflect.TypeOf(info.rawRequest)
|
|
||||||
if to.Kind() == reflect.Ptr {
|
|
||||||
to = to.Elem()
|
|
||||||
}
|
|
||||||
for i := 0; i < to.NumField(); i++ {
|
|
||||||
field := to.Field(i)
|
|
||||||
list = append(list, newFieldDescInfo(field))
|
|
||||||
}
|
|
||||||
info.Fields = list
|
|
||||||
return list
|
|
||||||
}
|
|
||||||
|
|
||||||
func (info *RouteDescInfo) HasRequest() bool {
|
|
||||||
return info.rawRequest != nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type FieldDescInfo struct {
|
|
||||||
Name string
|
|
||||||
FieldName string
|
|
||||||
Type string
|
|
||||||
Desc string
|
|
||||||
Required bool
|
|
||||||
Default string
|
|
||||||
rawTypeOfField reflect.StructField
|
|
||||||
}
|
|
||||||
|
|
||||||
func newFieldDescInfo(field reflect.StructField) *FieldDescInfo {
|
|
||||||
desc := &FieldDescInfo{
|
|
||||||
Name: field.Tag.Get("json"),
|
|
||||||
FieldName: field.Name,
|
|
||||||
Type: field.Type.String(),
|
|
||||||
Desc: field.Tag.Get("desc"),
|
|
||||||
rawTypeOfField: field,
|
|
||||||
}
|
|
||||||
if field.Tag.Get("required") == "true" {
|
|
||||||
desc.Required = true
|
|
||||||
}
|
|
||||||
desc.Default = desc.rawTypeOfField.Tag.Get("default")
|
|
||||||
return desc
|
|
||||||
}
|
|
@ -1,303 +0,0 @@
|
|||||||
package web
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"io"
|
|
||||||
"reflect"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
type routerGroupGin struct {
|
|
||||||
group *gin.RouterGroup
|
|
||||||
newContextFun func() Context
|
|
||||||
}
|
|
||||||
|
|
||||||
func (group *routerGroupGin) Use(middlewares ...HandlerFunc) {
|
|
||||||
group.group.Use(getGinHandlerFun(group.newContextFun, middlewares...)...)
|
|
||||||
}
|
|
||||||
func (group *routerGroupGin) Group(path string, handlers ...HandlerFunc) routeGroupInterface {
|
|
||||||
ginGroup := group.group.Group(path, getGinHandlerFun(group.newContextFun, handlers...)...)
|
|
||||||
group1 := &routerGroupGin{group: ginGroup, newContextFun: group.newContextFun}
|
|
||||||
return group1
|
|
||||||
}
|
|
||||||
func (group *routerGroupGin) Get(path string, desc string, req any, handlers ...HandlerFunc) routeGroupInterface {
|
|
||||||
if req == nil {
|
|
||||||
group.group.GET(path, getGinHandlerFun(group.newContextFun, handlers...)...)
|
|
||||||
} else {
|
|
||||||
group.group.GET(path, getGinHandlerFunWithRequest(group.newContextFun, req, handlers...)...)
|
|
||||||
}
|
|
||||||
return group
|
|
||||||
}
|
|
||||||
func (group *routerGroupGin) Post(path string, desc string, req any, handlers ...HandlerFunc) routeGroupInterface {
|
|
||||||
if req == nil {
|
|
||||||
group.group.POST(path, getGinHandlerFun(group.newContextFun, handlers...)...)
|
|
||||||
} else {
|
|
||||||
group.group.POST(path, getGinHandlerFunWithRequest(group.newContextFun, req, handlers...)...)
|
|
||||||
}
|
|
||||||
return group
|
|
||||||
}
|
|
||||||
|
|
||||||
func (group *routerGroupGin) Put(path string, desc string, req any, handlers ...HandlerFunc) routeGroupInterface {
|
|
||||||
if req == nil {
|
|
||||||
group.group.PUT(path, getGinHandlerFun(group.newContextFun, handlers...)...)
|
|
||||||
} else {
|
|
||||||
group.group.PUT(path, getGinHandlerFunWithRequest(group.newContextFun, req, handlers...)...)
|
|
||||||
}
|
|
||||||
return group
|
|
||||||
}
|
|
||||||
|
|
||||||
func (group *routerGroupGin) Delete(path string, desc string, req any, handlers ...HandlerFunc) routeGroupInterface {
|
|
||||||
if req == nil {
|
|
||||||
group.group.DELETE(path, getGinHandlerFun(group.newContextFun, handlers...)...)
|
|
||||||
} else {
|
|
||||||
group.group.DELETE(path, getGinHandlerFunWithRequest(group.newContextFun, req, handlers...)...)
|
|
||||||
}
|
|
||||||
return group
|
|
||||||
}
|
|
||||||
|
|
||||||
type routerGin struct {
|
|
||||||
engine *gin.Engine
|
|
||||||
newContextFun func() Context
|
|
||||||
}
|
|
||||||
|
|
||||||
func newRouterGin(newContextFun func() Context) routerInterface {
|
|
||||||
engine := gin.Default()
|
|
||||||
router := &routerGin{
|
|
||||||
engine: engine,
|
|
||||||
newContextFun: newContextFun,
|
|
||||||
}
|
|
||||||
return router
|
|
||||||
}
|
|
||||||
|
|
||||||
func (router *routerGin) Use(middlewares ...HandlerFunc) {
|
|
||||||
router.engine.Use(getGinHandlerFun(router.newContextFun, middlewares...)...)
|
|
||||||
}
|
|
||||||
func (router *routerGin) Group(path string, handlers ...HandlerFunc) routeGroupInterface {
|
|
||||||
ginGroup := router.engine.Group(path, getGinHandlerFun(router.newContextFun, handlers...)...)
|
|
||||||
group := &routerGroupGin{
|
|
||||||
group: ginGroup,
|
|
||||||
newContextFun: router.newContextFun,
|
|
||||||
}
|
|
||||||
return group
|
|
||||||
}
|
|
||||||
func (router *routerGin) Get(path string, desc string, req any, handlers ...HandlerFunc) routeGroupInterface {
|
|
||||||
if req == nil {
|
|
||||||
router.engine.GET(path, getGinHandlerFun(router.newContextFun, handlers...)...)
|
|
||||||
} else {
|
|
||||||
router.engine.GET(path, getGinHandlerFunWithRequest(router.newContextFun, req, handlers...)...)
|
|
||||||
}
|
|
||||||
return router
|
|
||||||
}
|
|
||||||
func (router *routerGin) Post(path string, desc string, req any, handlers ...HandlerFunc) routeGroupInterface {
|
|
||||||
if req == nil {
|
|
||||||
router.engine.POST(path, getGinHandlerFun(router.newContextFun, handlers...)...)
|
|
||||||
} else {
|
|
||||||
router.engine.POST(path, getGinHandlerFunWithRequest(router.newContextFun, req, handlers...)...)
|
|
||||||
}
|
|
||||||
return router
|
|
||||||
}
|
|
||||||
|
|
||||||
func (router *routerGin) Put(path string, desc string, req any, handlers ...HandlerFunc) routeGroupInterface {
|
|
||||||
if req == nil {
|
|
||||||
router.engine.PUT(path, getGinHandlerFun(router.newContextFun, handlers...)...)
|
|
||||||
} else {
|
|
||||||
router.engine.PUT(path, getGinHandlerFunWithRequest(router.newContextFun, req, handlers...)...)
|
|
||||||
}
|
|
||||||
return router
|
|
||||||
}
|
|
||||||
|
|
||||||
func (router *routerGin) Delete(path string, desc string, req any, handlers ...HandlerFunc) routeGroupInterface {
|
|
||||||
if req == nil {
|
|
||||||
router.engine.DELETE(path, getGinHandlerFun(router.newContextFun, handlers...)...)
|
|
||||||
} else {
|
|
||||||
router.engine.DELETE(path, getGinHandlerFunWithRequest(router.newContextFun, req, handlers...)...)
|
|
||||||
}
|
|
||||||
return router
|
|
||||||
}
|
|
||||||
|
|
||||||
func getGinHandlerFun(newContextFun func() Context, handlers ...HandlerFunc) []gin.HandlerFunc {
|
|
||||||
list := make([]gin.HandlerFunc, 0, len(handlers))
|
|
||||||
for _, handler := range handlers {
|
|
||||||
list = append(list, func(rawCtx *gin.Context) {
|
|
||||||
rawCtx1 := &ginCtx{ctx: rawCtx}
|
|
||||||
ctx := newContextFun()
|
|
||||||
ctx.SetRawContext(rawCtx1)
|
|
||||||
reflect.ValueOf(handler).Call([]reflect.Value{reflect.ValueOf(ctx)})
|
|
||||||
if rawCtx.IsAborted() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return list
|
|
||||||
}
|
|
||||||
|
|
||||||
func getGinHandlerFunWithRequest(newContextFun func() Context, requestTemplate any, handlers ...HandlerFunc) []gin.HandlerFunc {
|
|
||||||
list := make([]gin.HandlerFunc, 0, len(handlers))
|
|
||||||
for _, handler := range handlers {
|
|
||||||
list = append(list, func(rawCtx *gin.Context) {
|
|
||||||
rawCtx1 := &ginCtx{ctx: rawCtx}
|
|
||||||
ctx := newContextFun()
|
|
||||||
ctx.SetRawContext(rawCtx1)
|
|
||||||
request, err := rawCtx1.parseRequest(requestTemplate)
|
|
||||||
if err != nil {
|
|
||||||
ParseParamsErrorHandler(ctx, rawCtx.Request.RequestURI, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
reflect.ValueOf(handler).Call([]reflect.Value{reflect.ValueOf(ctx), reflect.ValueOf(request)})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return list
|
|
||||||
}
|
|
||||||
|
|
||||||
func (router *routerGin) Run(addr string) error {
|
|
||||||
return router.engine.Run(addr)
|
|
||||||
}
|
|
||||||
|
|
||||||
type ginCtx struct {
|
|
||||||
ctx *gin.Context
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ctx *ginCtx) Json(code int, v any) {
|
|
||||||
ctx.ctx.JSON(code, v)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ctx *ginCtx) Writer() io.Writer {
|
|
||||||
return ctx.ctx.Writer
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ctx *ginCtx) body() ([]byte, error) {
|
|
||||||
buf, err := io.ReadAll(ctx.ctx.Request.Body)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("read body error:%v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return buf, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ctx *ginCtx) parseRequest(request any) (any, error) {
|
|
||||||
if request == nil {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
requestType := reflect.TypeOf(request)
|
|
||||||
newRequest := reflect.New(requestType).Interface()
|
|
||||||
|
|
||||||
body, err := ctx.body()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(body) == 0 {
|
|
||||||
newRequestValue := reflect.ValueOf(newRequest).Elem()
|
|
||||||
newRequestValueType := newRequestValue.Type()
|
|
||||||
for i := 0; i < newRequestValue.NumField(); i++ {
|
|
||||||
f := newRequestValueType.Field(i)
|
|
||||||
fieldTagName := f.Tag.Get("json")
|
|
||||||
if fieldTagName == "" {
|
|
||||||
fieldTagName = f.Name
|
|
||||||
}
|
|
||||||
|
|
||||||
field := newRequestValue.Field(i)
|
|
||||||
if !field.CanSet() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
fieldStr := ctx.ctx.Query(fieldTagName)
|
|
||||||
err := setValue(field, fieldStr, f.Tag.Get("default"), f.Tag.Get("required"))
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("parse uri params field(%v) set value(%v) error:%v", f.Name, fieldStr, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
err = json.Unmarshal(body, newRequest)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("json unmarshal body error:%v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return newRequest, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// setValue 设置结构体一个字段的值
|
|
||||||
func setValue(field reflect.Value, value string, defaultValue string, required string) error {
|
|
||||||
if value == "" {
|
|
||||||
value = defaultValue
|
|
||||||
}
|
|
||||||
if value == "" && required == "true" {
|
|
||||||
return fmt.Errorf("field is required, please give a valid value")
|
|
||||||
}
|
|
||||||
|
|
||||||
if field.Kind() == reflect.Ptr {
|
|
||||||
if value == "" {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if field.IsNil() {
|
|
||||||
field.Set(reflect.New(field.Type().Elem()))
|
|
||||||
}
|
|
||||||
field = field.Elem()
|
|
||||||
}
|
|
||||||
switch field.Kind() {
|
|
||||||
case reflect.String:
|
|
||||||
field.SetString(value)
|
|
||||||
case reflect.Bool:
|
|
||||||
if value == "" {
|
|
||||||
field.SetBool(false)
|
|
||||||
} else {
|
|
||||||
b, err := strconv.ParseBool(value)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
field.SetBool(b)
|
|
||||||
}
|
|
||||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
|
||||||
if value == "" {
|
|
||||||
field.SetInt(0)
|
|
||||||
} else {
|
|
||||||
i, err := strconv.ParseInt(value, 0, field.Type().Bits())
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
field.SetInt(i)
|
|
||||||
}
|
|
||||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
|
||||||
if value == "" {
|
|
||||||
field.SetUint(0)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
ui, err := strconv.ParseUint(value, 0, field.Type().Bits())
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
field.SetUint(ui)
|
|
||||||
case reflect.Float32, reflect.Float64:
|
|
||||||
if value == "" {
|
|
||||||
field.SetFloat(0)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
f, err := strconv.ParseFloat(value, field.Type().Bits())
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
field.SetFloat(f)
|
|
||||||
case reflect.Struct:
|
|
||||||
return fmt.Errorf("unsupport struct field:%v", field.Type())
|
|
||||||
case reflect.Slice:
|
|
||||||
values := strings.Split(value, ",")
|
|
||||||
if len(values) == 1 && values[0] == "" {
|
|
||||||
values = []string{}
|
|
||||||
}
|
|
||||||
field.Set(reflect.MakeSlice(field.Type(), len(values), len(values)))
|
|
||||||
for i := 0; i < len(values); i++ {
|
|
||||||
err := setValue(field.Index(i), values[i], "", "")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("no support type %s", field.Type())
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
228
admin/lib/web/routes_group.go
Normal file
228
admin/lib/web/routes_group.go
Normal file
@ -0,0 +1,228 @@
|
|||||||
|
package web
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"io"
|
||||||
|
"reflect"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type IContext interface {
|
||||||
|
HandleError(path string, err error)
|
||||||
|
HandleSuccess(rspData any)
|
||||||
|
}
|
||||||
|
|
||||||
|
type HandlerFunc any
|
||||||
|
|
||||||
|
type RoutesGroup struct {
|
||||||
|
newContextFun func(ctx *gin.Context) IContext
|
||||||
|
rawGroup *gin.RouterGroup
|
||||||
|
node *routesNode
|
||||||
|
}
|
||||||
|
|
||||||
|
func newRoutesGroup(rawGroup *gin.RouterGroup, newContextFun func(ctx *gin.Context) IContext) *RoutesGroup {
|
||||||
|
g := &RoutesGroup{
|
||||||
|
rawGroup: rawGroup,
|
||||||
|
newContextFun: newContextFun,
|
||||||
|
node: &routesNode{},
|
||||||
|
}
|
||||||
|
return g
|
||||||
|
}
|
||||||
|
|
||||||
|
func (group *RoutesGroup) Group(path string, desc string, handlers ...HandlerFunc) *RoutesGroup {
|
||||||
|
rawGroup := group.rawGroup.Group(path, getGinHandlerFunWithRequest(group.newContextFun, handlers...)...)
|
||||||
|
nextRoutesGroup := newRoutesGroup(rawGroup, group.newContextFun)
|
||||||
|
nextGroupNode := group.addChildren("", path, desc, 0, handlers...)
|
||||||
|
nextRoutesGroup.node = nextGroupNode
|
||||||
|
return nextRoutesGroup
|
||||||
|
}
|
||||||
|
|
||||||
|
func (group *RoutesGroup) Use(middlewares ...HandlerFunc) {
|
||||||
|
group.rawGroup.Use(getGinHandlerFunWithRequest(group.newContextFun, middlewares...)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (group *RoutesGroup) Get(path string, desc string, permit int, handlers ...HandlerFunc) {
|
||||||
|
group.rawGroup.GET(path, getGinHandlerFunWithRequest(group.newContextFun, handlers...)...)
|
||||||
|
group.addChildren("GET", path, desc, permit, handlers...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (group *RoutesGroup) Post(path string, desc string, permit int, handlers ...HandlerFunc) {
|
||||||
|
group.rawGroup.POST(path, getGinHandlerFunWithRequest(group.newContextFun, handlers...)...)
|
||||||
|
group.addChildren("POST", path, desc, permit, handlers...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (group *RoutesGroup) Put(path string, desc string, permit int, handlers ...HandlerFunc) {
|
||||||
|
group.rawGroup.PUT(path, getGinHandlerFunWithRequest(group.newContextFun, handlers...)...)
|
||||||
|
group.addChildren("PUT", path, desc, permit, handlers...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (group *RoutesGroup) Delete(path string, desc string, permit int, handlers ...HandlerFunc) {
|
||||||
|
group.rawGroup.DELETE(path, getGinHandlerFunWithRequest(group.newContextFun, handlers...)...)
|
||||||
|
group.addChildren("DELETE", path, desc, permit, handlers...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (group *RoutesGroup) addChildren(method, path string, desc string, permit int, handlers ...HandlerFunc) *routesNode {
|
||||||
|
return group.node.addChildren(method, path, desc, permit, handlers...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getGinHandlerFunWithRequest(newContextFun func(ctx *gin.Context) IContext, handlers ...HandlerFunc) []gin.HandlerFunc {
|
||||||
|
list := make([]gin.HandlerFunc, 0, len(handlers))
|
||||||
|
|
||||||
|
for _, handler := range handlers {
|
||||||
|
list = append(list, func(rawCtx *gin.Context) {
|
||||||
|
|
||||||
|
ctx := newContextFun(rawCtx)
|
||||||
|
|
||||||
|
handlerTo := reflect.TypeOf(handler)
|
||||||
|
numParams := handlerTo.NumIn()
|
||||||
|
if numParams != 3 {
|
||||||
|
ctx.HandleError(rawCtx.Request.RequestURI, fmt.Errorf("register callback handler params len(%v) invalid", numParams))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
paramsTo := handlerTo.In(1)
|
||||||
|
params := reflect.New(paramsTo.Elem()).Interface()
|
||||||
|
err := parseRequest(rawCtx, params)
|
||||||
|
if err != nil {
|
||||||
|
ctx.HandleError(rawCtx.Request.RequestURI, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
rspTo := handlerTo.In(2)
|
||||||
|
rsp := reflect.New(rspTo.Elem()).Interface()
|
||||||
|
rets := reflect.ValueOf(handler).Call([]reflect.Value{reflect.ValueOf(ctx), reflect.ValueOf(params), reflect.ValueOf(rsp)})
|
||||||
|
errInt := rets[0]
|
||||||
|
if errInt.Interface() == nil {
|
||||||
|
ctx.HandleSuccess(rsp)
|
||||||
|
} else {
|
||||||
|
err, ok := errInt.Interface().(error)
|
||||||
|
if ok {
|
||||||
|
ctx.HandleError(rawCtx.Request.RequestURI, err)
|
||||||
|
} else {
|
||||||
|
ctx.HandleError(rawCtx.Request.RequestURI, fmt.Errorf("handle request ret error, but parse return error:%+v not ok", err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return list
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseRequest(rawCtx *gin.Context, params any) error {
|
||||||
|
bodyBuf, err := io.ReadAll(rawCtx.Request.Body)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("read body error:%v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(bodyBuf) == 0 {
|
||||||
|
newRequestValue := reflect.ValueOf(params).Elem()
|
||||||
|
newRequestValueType := newRequestValue.Type()
|
||||||
|
for i := 0; i < newRequestValue.NumField(); i++ {
|
||||||
|
f := newRequestValueType.Field(i)
|
||||||
|
fieldTagName := f.Tag.Get("json")
|
||||||
|
if fieldTagName == "" {
|
||||||
|
fieldTagName = f.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
field := newRequestValue.Field(i)
|
||||||
|
if !field.CanSet() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fieldStr := rawCtx.Query(fieldTagName)
|
||||||
|
err := setValue(field, fieldStr, f.Tag.Get("default"), f.Tag.Get("required"))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("parse uri params field(%v) set value(%v) error:%v", f.Name, fieldStr, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
err = json.Unmarshal(bodyBuf, params)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("json unmarshal body error:%v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// setValue 设置结构体一个字段的值
|
||||||
|
func setValue(field reflect.Value, value string, defaultValue string, required string) error {
|
||||||
|
if value == "" {
|
||||||
|
value = defaultValue
|
||||||
|
}
|
||||||
|
if value == "" && required == "true" {
|
||||||
|
return fmt.Errorf("field is required, please give a valid value")
|
||||||
|
}
|
||||||
|
|
||||||
|
if field.Kind() == reflect.Ptr {
|
||||||
|
if value == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if field.IsNil() {
|
||||||
|
field.Set(reflect.New(field.Type().Elem()))
|
||||||
|
}
|
||||||
|
field = field.Elem()
|
||||||
|
}
|
||||||
|
switch field.Kind() {
|
||||||
|
case reflect.String:
|
||||||
|
field.SetString(value)
|
||||||
|
case reflect.Bool:
|
||||||
|
if value == "" {
|
||||||
|
field.SetBool(false)
|
||||||
|
} else {
|
||||||
|
b, err := strconv.ParseBool(value)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
field.SetBool(b)
|
||||||
|
}
|
||||||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
|
if value == "" {
|
||||||
|
field.SetInt(0)
|
||||||
|
} else {
|
||||||
|
i, err := strconv.ParseInt(value, 0, field.Type().Bits())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
field.SetInt(i)
|
||||||
|
}
|
||||||
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||||
|
if value == "" {
|
||||||
|
field.SetUint(0)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
ui, err := strconv.ParseUint(value, 0, field.Type().Bits())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
field.SetUint(ui)
|
||||||
|
case reflect.Float32, reflect.Float64:
|
||||||
|
if value == "" {
|
||||||
|
field.SetFloat(0)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
f, err := strconv.ParseFloat(value, field.Type().Bits())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
field.SetFloat(f)
|
||||||
|
case reflect.Struct:
|
||||||
|
return fmt.Errorf("unsupport struct field:%v", field.Type())
|
||||||
|
case reflect.Slice:
|
||||||
|
values := strings.Split(value, ",")
|
||||||
|
if len(values) == 1 && values[0] == "" {
|
||||||
|
values = []string{}
|
||||||
|
}
|
||||||
|
field.Set(reflect.MakeSlice(field.Type(), len(values), len(values)))
|
||||||
|
for i := 0; i < len(values); i++ {
|
||||||
|
err := setValue(field.Index(i), values[i], "", "")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("no support type %s", field.Type())
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
@ -125,7 +125,7 @@ func SetLogLevel(level LogLevel) {
|
|||||||
func ParseLogLevelString(level string) LogLevel {
|
func ParseLogLevelString(level string) LogLevel {
|
||||||
lvEnum, find := LogLevelStr2Enum[level]
|
lvEnum, find := LogLevelStr2Enum[level]
|
||||||
if !find {
|
if !find {
|
||||||
return LogLevelDebug
|
return LogLevelTrace
|
||||||
}
|
}
|
||||||
return lvEnum
|
return lvEnum
|
||||||
}
|
}
|
||||||
|
124
ui/package-lock.json
generated
124
ui/package-lock.json
generated
@ -17,6 +17,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vitejs/plugin-vue": "^5.2.3",
|
"@vitejs/plugin-vue": "^5.2.3",
|
||||||
"unplugin-auto-import": "^19.1.2",
|
"unplugin-auto-import": "^19.1.2",
|
||||||
|
"unplugin-icons": "^22.1.0",
|
||||||
"unplugin-vue-components": "^28.5.0",
|
"unplugin-vue-components": "^28.5.0",
|
||||||
"vite": "^6.2.4",
|
"vite": "^6.2.4",
|
||||||
"vite-plugin-vue-devtools": "^7.7.2"
|
"vite-plugin-vue-devtools": "^7.7.2"
|
||||||
@ -36,6 +37,20 @@
|
|||||||
"node": ">=6.0.0"
|
"node": ">=6.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@antfu/install-pkg": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/@antfu/install-pkg/-/install-pkg-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-xvX6P/lo1B3ej0OsaErAjqgFYzYVcJpamjLAFLYh9vRJngBrMoUG7aVnrGTeqM7yxbyTD5p3F2+0/QUEh8Vzhw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"package-manager-detector": "^0.2.8",
|
||||||
|
"tinyexec": "^0.3.2"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/antfu"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@antfu/utils": {
|
"node_modules/@antfu/utils": {
|
||||||
"version": "0.7.10",
|
"version": "0.7.10",
|
||||||
"resolved": "https://registry.npmmirror.com/@antfu/utils/-/utils-0.7.10.tgz",
|
"resolved": "https://registry.npmmirror.com/@antfu/utils/-/utils-0.7.10.tgz",
|
||||||
@ -959,6 +974,53 @@
|
|||||||
"integrity": "sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==",
|
"integrity": "sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/@iconify/types": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/@iconify/types/-/types-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/@iconify/utils": {
|
||||||
|
"version": "2.3.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/@iconify/utils/-/utils-2.3.0.tgz",
|
||||||
|
"integrity": "sha512-GmQ78prtwYW6EtzXRU1rY+KwOKfz32PD7iJh6Iyqw68GiKuoZ2A6pRtzWONz5VQJbp50mEjXh/7NkumtrAgRKA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@antfu/install-pkg": "^1.0.0",
|
||||||
|
"@antfu/utils": "^8.1.0",
|
||||||
|
"@iconify/types": "^2.0.0",
|
||||||
|
"debug": "^4.4.0",
|
||||||
|
"globals": "^15.14.0",
|
||||||
|
"kolorist": "^1.8.0",
|
||||||
|
"local-pkg": "^1.0.0",
|
||||||
|
"mlly": "^1.7.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@iconify/utils/node_modules/@antfu/utils": {
|
||||||
|
"version": "8.1.1",
|
||||||
|
"resolved": "https://registry.npmmirror.com/@antfu/utils/-/utils-8.1.1.tgz",
|
||||||
|
"integrity": "sha512-Mex9nXf9vR6AhcXmMrlz/HVgYYZpVGJ6YlPgwl7UnaFpnshXs6EK/oa5Gpf3CzENMjkvEx2tQtntGnb7UtSTOQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/antfu"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@iconify/utils/node_modules/globals": {
|
||||||
|
"version": "15.15.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/globals/-/globals-15.15.0.tgz",
|
||||||
|
"integrity": "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@jridgewell/gen-mapping": {
|
"node_modules/@jridgewell/gen-mapping": {
|
||||||
"version": "0.3.8",
|
"version": "0.3.8",
|
||||||
"resolved": "https://registry.npmmirror.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz",
|
"resolved": "https://registry.npmmirror.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz",
|
||||||
@ -3001,6 +3063,16 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/package-manager-detector": {
|
||||||
|
"version": "0.2.11",
|
||||||
|
"resolved": "https://registry.npmmirror.com/package-manager-detector/-/package-manager-detector-0.2.11.tgz",
|
||||||
|
"integrity": "sha512-BEnLolu+yuz22S56CU1SUKq3XC3PkwD5wv4ikR4MfGvnRVcmzXR9DwSlW2fEamyTPyXHomBJRzgapeuBvRNzJQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"quansync": "^0.2.7"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/parse-ms": {
|
"node_modules/parse-ms": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmmirror.com/parse-ms/-/parse-ms-4.0.0.tgz",
|
"resolved": "https://registry.npmmirror.com/parse-ms/-/parse-ms-4.0.0.tgz",
|
||||||
@ -3372,6 +3444,13 @@
|
|||||||
"node": ">=16"
|
"node": ">=16"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/tinyexec": {
|
||||||
|
"version": "0.3.2",
|
||||||
|
"resolved": "https://registry.npmmirror.com/tinyexec/-/tinyexec-0.3.2.tgz",
|
||||||
|
"integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/tinyglobby": {
|
"node_modules/tinyglobby": {
|
||||||
"version": "0.2.12",
|
"version": "0.2.12",
|
||||||
"resolved": "https://registry.npmmirror.com/tinyglobby/-/tinyglobby-0.2.12.tgz",
|
"resolved": "https://registry.npmmirror.com/tinyglobby/-/tinyglobby-0.2.12.tgz",
|
||||||
@ -3526,6 +3605,51 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/unplugin-icons": {
|
||||||
|
"version": "22.1.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/unplugin-icons/-/unplugin-icons-22.1.0.tgz",
|
||||||
|
"integrity": "sha512-ect2ZNtk1Zgwb0NVHd0C1IDW/MV+Jk/xaq4t8o6rYdVS3+L660ZdD5kTSQZvsgdwCvquRw+/wYn75hsweRjoIA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@antfu/install-pkg": "^1.0.0",
|
||||||
|
"@iconify/utils": "^2.3.0",
|
||||||
|
"debug": "^4.4.0",
|
||||||
|
"local-pkg": "^1.0.0",
|
||||||
|
"unplugin": "^2.2.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/antfu"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@svgr/core": ">=7.0.0",
|
||||||
|
"@svgx/core": "^1.0.1",
|
||||||
|
"@vue/compiler-sfc": "^3.0.2 || ^2.7.0",
|
||||||
|
"svelte": "^3.0.0 || ^4.0.0 || ^5.0.0",
|
||||||
|
"vue-template-compiler": "^2.6.12",
|
||||||
|
"vue-template-es2015-compiler": "^1.9.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@svgr/core": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@svgx/core": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@vue/compiler-sfc": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"svelte": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"vue-template-compiler": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"vue-template-es2015-compiler": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/unplugin-utils": {
|
"node_modules/unplugin-utils": {
|
||||||
"version": "0.2.4",
|
"version": "0.2.4",
|
||||||
"resolved": "https://registry.npmmirror.com/unplugin-utils/-/unplugin-utils-0.2.4.tgz",
|
"resolved": "https://registry.npmmirror.com/unplugin-utils/-/unplugin-utils-0.2.4.tgz",
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vitejs/plugin-vue": "^5.2.3",
|
"@vitejs/plugin-vue": "^5.2.3",
|
||||||
"unplugin-auto-import": "^19.1.2",
|
"unplugin-auto-import": "^19.1.2",
|
||||||
|
"unplugin-icons": "^22.1.0",
|
||||||
"unplugin-vue-components": "^28.5.0",
|
"unplugin-vue-components": "^28.5.0",
|
||||||
"vite": "^6.2.4",
|
"vite": "^6.2.4",
|
||||||
"vite-plugin-vue-devtools": "^7.7.2"
|
"vite-plugin-vue-devtools": "^7.7.2"
|
||||||
|
9
ui/src/api/game_api.js
Normal file
9
ui/src/api/game_api.js
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import request from '@/utils/request'
|
||||||
|
|
||||||
|
export function gameApiRequest(url, method, data) {
|
||||||
|
return request({
|
||||||
|
url: url,
|
||||||
|
method: method,
|
||||||
|
params: data
|
||||||
|
})
|
||||||
|
}
|
@ -1,9 +0,0 @@
|
|||||||
import request from '@/utils/request'
|
|
||||||
|
|
||||||
export function getProjectList(params) {
|
|
||||||
return request({
|
|
||||||
url: '/project',
|
|
||||||
method: 'get',
|
|
||||||
params: params
|
|
||||||
})
|
|
||||||
}
|
|
34
ui/src/api/resource.js
Normal file
34
ui/src/api/resource.js
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import request from '@/utils/request'
|
||||||
|
|
||||||
|
export function resourceList(url, params) {
|
||||||
|
return request({
|
||||||
|
url: url,
|
||||||
|
method: 'get',
|
||||||
|
data: params
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function resourcePost(url, params) {
|
||||||
|
return request({
|
||||||
|
url: url,
|
||||||
|
method: 'post',
|
||||||
|
data: {'dto': params}
|
||||||
|
// params: {'dto': params}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function resourcePut(url, params) {
|
||||||
|
return request({
|
||||||
|
url: url,
|
||||||
|
method: 'put',
|
||||||
|
data: {'dto': params}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function resourceDelete(url, params) {
|
||||||
|
return request({
|
||||||
|
url: url,
|
||||||
|
method: 'delete',
|
||||||
|
data: params
|
||||||
|
})
|
||||||
|
}
|
@ -1,38 +1,219 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
|
import {ElNotification} from "element-plus";
|
||||||
|
import {resourceDelete, resourceList, resourcePost, resourcePut} from "@/api/resource.js";
|
||||||
|
import {ref, toRaw} from "vue";
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
rows: {}
|
// rows: {},
|
||||||
|
resource_url: '',
|
||||||
|
row_click_handler: null,
|
||||||
})
|
})
|
||||||
|
|
||||||
const fieldsDescInfo = props.rows.fields_desc
|
const listRsp = ref({fields_desc: [], rows: []})
|
||||||
const rows = props.rows.rows
|
const getListOk = ref(false)
|
||||||
|
const resource_url = props.resource_url
|
||||||
|
const fieldsDescInfo = ref([])
|
||||||
|
const rows = ref([])
|
||||||
|
const rules = ref({})
|
||||||
|
|
||||||
console.log("fields desc:", fieldsDescInfo)
|
const listData = async () => {
|
||||||
console.log("rows:", props.rows)
|
try {
|
||||||
|
const rspData = await resourceList(resource_url, {page_no: 0, page_len: 100});
|
||||||
|
listRsp.value = rspData;
|
||||||
|
if (listRsp.value.code !== 200) throw new Error("请求失败,错误码:", listRsp.code);
|
||||||
|
fieldsDescInfo.value = listRsp.value.data.fields_desc
|
||||||
|
rows.value = listRsp.value.data.rows
|
||||||
|
|
||||||
|
|
||||||
|
for (let i = 0; i < fieldsDescInfo.value.length; i++) {
|
||||||
|
var field = fieldsDescInfo.value[i]
|
||||||
|
dialogAddForm.value[field.key] = ''
|
||||||
|
if (field.require == true) {
|
||||||
|
rules.value[field.key] = [{required: true, message: field.name + "不能为空", trigger: "blur"}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('await list rsp:', listRsp.value)
|
||||||
|
console.log("await fields:", fieldsDescInfo.value)
|
||||||
|
console.log("await rows:", toRaw(rows.value))
|
||||||
|
console.log("await rules:", toRaw(rules.value))
|
||||||
|
|
||||||
|
getListOk.value = true
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err)
|
||||||
|
} finally {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
listData();
|
||||||
|
})
|
||||||
|
|
||||||
|
const dialogAddVisible = ref(false)
|
||||||
|
const dialogEditVisible = ref(false)
|
||||||
|
const dialogAddFormRef = ref(null)
|
||||||
|
const dialogEditFormRef = ref(null)
|
||||||
|
|
||||||
|
const dialogAddForm = ref({})
|
||||||
|
const dialogEditForm = ref({})
|
||||||
|
|
||||||
|
|
||||||
|
const submitAdd = async () => {
|
||||||
|
try {
|
||||||
|
await dialogAddFormRef.value.validate(valid => {
|
||||||
|
if (valid) {
|
||||||
|
resourcePost(resource_url, dialogAddForm.value).then((res) => {
|
||||||
|
ElNotification({
|
||||||
|
title: "添加结果通知",
|
||||||
|
message: "添加成功!",
|
||||||
|
type: 'success',
|
||||||
|
duration: 4000,
|
||||||
|
"show-close": true,
|
||||||
|
})
|
||||||
|
rows.value.push(dialogAddForm.value)
|
||||||
|
dialogAddVisible.value = false
|
||||||
|
}, (err) => {
|
||||||
|
console.log("添加报错:", err)
|
||||||
|
})
|
||||||
|
console.log("提交数据:", dialogAddForm.value)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} catch (error) {
|
||||||
|
console.log("校验失败:", error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const submitEdit = async () => {
|
||||||
|
try {
|
||||||
|
await dialogEditFormRef.value.validate(valid => {
|
||||||
|
if (valid) {
|
||||||
|
resourcePut(resource_url, dialogEditForm.value).then((res) => {
|
||||||
|
ElNotification({
|
||||||
|
title: "编辑结果通知",
|
||||||
|
message: "编辑成功!",
|
||||||
|
type: 'success',
|
||||||
|
duration: 4000,
|
||||||
|
"show-close": true,
|
||||||
|
})
|
||||||
|
dialogEditVisible.value = false
|
||||||
|
rows.value[dialogEditForm.value.oldIndex] = res.data.dto
|
||||||
|
}, (err) => {
|
||||||
|
console.log("添加报错:", err)
|
||||||
|
})
|
||||||
|
console.log("提交数据:", dialogEditForm.value)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} catch (error) {
|
||||||
|
console.log("校验失败:", error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleEdit = (oper, index, row) => {
|
||||||
|
dialogEditForm.value.oldData = row
|
||||||
|
dialogEditForm.value.oldIndex = index
|
||||||
|
dialogEditForm.value = row
|
||||||
|
console.log("edit data:", row)
|
||||||
|
dialogEditVisible.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleDelete = (oper, index, row) => {
|
||||||
|
resourceDelete(resource_url, {id: row.ID}).then((res) => {
|
||||||
|
ElNotification({
|
||||||
|
title: "删除结果通知",
|
||||||
|
message: "删除指令服务器[" + row.name + "]成功!",
|
||||||
|
type: 'success',
|
||||||
|
duration: 4000,
|
||||||
|
"show-close": true,
|
||||||
|
})
|
||||||
|
rows.value.splice(index, 1)
|
||||||
|
}, (err) => {
|
||||||
|
console.log("delet error:", err)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const tableRowClick = (index, row) => {
|
||||||
|
console.log("row is clicked:", row)
|
||||||
|
if (props.row_click_handler != null) {
|
||||||
|
props.row_click_handler(row)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleCloseDialog = () => {
|
||||||
|
dialogAddVisible.value = false
|
||||||
|
dialogEditVisible.value = false
|
||||||
|
dialogAddForm.value = {}
|
||||||
|
dialogEditForm.value = {}
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<el-container v-if="getListOk">
|
||||||
<el-container>
|
|
||||||
<el-header>
|
<el-header>
|
||||||
<el-button size="large" type="primary">添加</el-button>
|
<el-button @click="dialogAddVisible = true" size="large" type="primary">添加</el-button>
|
||||||
</el-header>
|
</el-header>
|
||||||
<el-main>
|
<el-main>
|
||||||
<el-table :data="rows" style="width: 100%" table-layout="auto" stripe>
|
<el-table :data="rows" style="width: 100%" table-layout="auto" stripe>
|
||||||
<template v-for="fieldDescInfo in fieldsDescInfo">
|
<template v-for="fieldDescInfo in fieldsDescInfo">
|
||||||
<el-table-column :prop="fieldDescInfo.key" :label="fieldDescInfo.name"></el-table-column>/
|
<el-table-column :prop="fieldDescInfo.key" :label="fieldDescInfo.name"></el-table-column>
|
||||||
</template>
|
</template>
|
||||||
|
<el-table-column prop="func" label="功 能">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-button size="large" type="primary" @click="tableRowClick(scope.$index, scope.row)">
|
||||||
|
<el-icon style="vertical-align: middle">
|
||||||
|
<ArrowRightBold/>
|
||||||
|
</el-icon>
|
||||||
|
<span>进入</span>
|
||||||
|
</el-button>
|
||||||
|
<el-button size="large" type="success" @click="handleEdit('operation', scope.$index, scope.row)">
|
||||||
|
<el-icon style="vertical-align: middle">
|
||||||
|
<Operation/>
|
||||||
|
</el-icon>
|
||||||
|
<span>编辑</span>
|
||||||
|
</el-button>
|
||||||
|
<el-button size="large" type="danger" @click="handleDelete('operation', scope.$index, scope.row)">
|
||||||
|
<el-icon style="vertical-align: middle">
|
||||||
|
<Delete/>
|
||||||
|
</el-icon>
|
||||||
|
<span>删除</span>
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
||||||
<el-dialog v-model="addvisible" title="添加" modal="true" :before-close="handleCloseAdd" destroy-on-close>
|
<el-dialog v-model="dialogAddVisible" :mask="true" title="添加" :modal="true" :before-close="handleCloseDialog"
|
||||||
|
destroy-on-close>
|
||||||
|
<el-form ref="dialogAddFormRef" :model="dialogAddForm" :rules="rules">
|
||||||
|
<template v-for="fieldDescInfo in fieldsDescInfo">
|
||||||
|
<el-form-item :label="fieldDescInfo.name" :prop="fieldDescInfo.key">
|
||||||
|
<el-input v-model="dialogAddForm[fieldDescInfo.key]" :placeholder="fieldDescInfo.name"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<el-form-item>
|
||||||
|
<el-button @click="submitAdd(dialogAddFormRef)" size="large" type="primary">提交</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-dialog>
|
||||||
|
|
||||||
|
<el-dialog v-model="dialogEditVisible" :mask="true" title="编辑" :modal="true" :before-close="handleCloseDialog"
|
||||||
|
destroy-on-close>
|
||||||
|
<el-form ref="dialogEditFormRef" :model="dialogEditForm" :rules="rules">
|
||||||
|
<template v-for="fieldDescInfo in fieldsDescInfo">
|
||||||
|
<el-form-item :label="fieldDescInfo.name" :prop="fieldDescInfo.key">
|
||||||
|
<el-input v-model="dialogEditForm[fieldDescInfo.key]"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<el-form-item>
|
||||||
|
<el-button @click="submitEdit(dialogEditFormRef)" size="large" type="primary">提交</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
</el-main>
|
</el-main>
|
||||||
</el-container>
|
</el-container>
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
@ -6,9 +6,14 @@ import ElementPlus from 'element-plus'
|
|||||||
import 'element-plus/dist/index.css'
|
import 'element-plus/dist/index.css'
|
||||||
import App from './App.vue'
|
import App from './App.vue'
|
||||||
import router from './router'
|
import router from './router'
|
||||||
|
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
|
||||||
|
|
||||||
const app = createApp(App)
|
const app = createApp(App)
|
||||||
|
|
||||||
|
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
|
||||||
|
app.component(key, component)
|
||||||
|
}
|
||||||
|
|
||||||
app.use(ElementPlus)
|
app.use(ElementPlus)
|
||||||
app.use(createPinia())
|
app.use(createPinia())
|
||||||
app.use(router)
|
app.use(router)
|
||||||
|
@ -1,6 +1,12 @@
|
|||||||
import { createRouter, createWebHistory } from 'vue-router'
|
import {createRouter, createWebHistory} from 'vue-router'
|
||||||
import Home from '../views/Home.vue'
|
import Home from '../views/Home.vue'
|
||||||
|
|
||||||
|
const query = () => {
|
||||||
|
return {
|
||||||
|
t: Date.now(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
history: createWebHistory(import.meta.env.BASE_URL),
|
history: createWebHistory(import.meta.env.BASE_URL),
|
||||||
routes: [
|
routes: [
|
||||||
@ -12,12 +18,20 @@ const router = createRouter({
|
|||||||
{
|
{
|
||||||
path: '/user',
|
path: '/user',
|
||||||
name: 'user',
|
name: 'user',
|
||||||
component: import('@/views/user/user.vue')
|
component: () => import('@/views/user/user.vue')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/project',
|
path: '/project',
|
||||||
name: 'project',
|
name: 'project',
|
||||||
component: import('@/views/project/project.vue')
|
component: () => import('@/views/project/project.vue'),
|
||||||
|
query: query(),
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'operation',
|
||||||
|
name: "ProjectOperation",
|
||||||
|
component: () => import('@/views/project/operation.vue')
|
||||||
|
},
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -1,12 +0,0 @@
|
|||||||
import { ref, computed } from 'vue'
|
|
||||||
import { defineStore } from 'pinia'
|
|
||||||
|
|
||||||
export const useCounterStore = defineStore('counter', () => {
|
|
||||||
const count = ref(0)
|
|
||||||
const doubleCount = computed(() => count.value * 2)
|
|
||||||
function increment() {
|
|
||||||
count.value++
|
|
||||||
}
|
|
||||||
|
|
||||||
return { count, doubleCount, increment }
|
|
||||||
})
|
|
12
ui/src/stores/project.js
Normal file
12
ui/src/stores/project.js
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import {ref} from 'vue'
|
||||||
|
import {defineStore} from 'pinia'
|
||||||
|
|
||||||
|
export const cachedProject = defineStore('clickedProject', () => {
|
||||||
|
const project = ref({})
|
||||||
|
const set = (setProject) => project.value = setProject
|
||||||
|
const get = () => project.value
|
||||||
|
return {
|
||||||
|
set,
|
||||||
|
get,
|
||||||
|
}
|
||||||
|
})
|
@ -1,6 +1,6 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { useRouter, useRoute } from 'vue-router'
|
import {useRoute, useRouter} from 'vue-router'
|
||||||
import { computed } from 'vue'
|
import {computed} from 'vue'
|
||||||
import avatarUrl from '@/assets/icon/header.png'
|
import avatarUrl from '@/assets/icon/header.png'
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
@ -34,8 +34,10 @@ const handleMenuSelect = (index) => {
|
|||||||
</el-menu>
|
</el-menu>
|
||||||
</el-aside>
|
</el-aside>
|
||||||
<el-container>
|
<el-container>
|
||||||
<el-header>Header</el-header>
|
<el-header>游戏后台管理系统</el-header>
|
||||||
<el-header><router-view/></el-header>
|
<el-main>
|
||||||
|
<router-view/>
|
||||||
|
</el-main>
|
||||||
</el-container>
|
</el-container>
|
||||||
</el-container>
|
</el-container>
|
||||||
</div>
|
</div>
|
||||||
|
49
ui/src/views/project/operation.vue
Normal file
49
ui/src/views/project/operation.vue
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
<script setup>
|
||||||
|
import {cachedProject} from '@/stores/project.js'
|
||||||
|
import {gameApiRequest} from '@/api/game_api.js'
|
||||||
|
|
||||||
|
const cachedProject1 = cachedProject()
|
||||||
|
|
||||||
|
const curProject = cachedProject1.get()
|
||||||
|
|
||||||
|
const commandList = ref([])
|
||||||
|
|
||||||
|
console.log("handle project:", curProject)
|
||||||
|
console.log("command api addr:", curProject.ApiAddr)
|
||||||
|
|
||||||
|
gameApiRequest("/project/commandlist", "get", {addr: curProject.ApiAddr}).then((res) => {
|
||||||
|
// console.log("请求commandlist成功!", res)
|
||||||
|
commandList.value = res.data.list
|
||||||
|
}, (err) => {
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<el-container>
|
||||||
|
<el-aside width="200px">
|
||||||
|
<el-menu
|
||||||
|
:default-active="activeMenu"
|
||||||
|
@select="handleMenuSelect"
|
||||||
|
>
|
||||||
|
<el-menu-item index="/user">
|
||||||
|
<span>用户管理</span>
|
||||||
|
</el-menu-item>
|
||||||
|
<el-menu-item index="/project">
|
||||||
|
<span>项目管理</span>
|
||||||
|
</el-menu-item>
|
||||||
|
</el-menu>
|
||||||
|
</el-aside>
|
||||||
|
<el-container>
|
||||||
|
<el-header>游戏后台管理系统</el-header>
|
||||||
|
<el-main>
|
||||||
|
<router-view/>
|
||||||
|
</el-main>
|
||||||
|
</el-container>
|
||||||
|
</el-container>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
@ -1,27 +1,33 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import {ref} from "vue";
|
|
||||||
import {getProjectList} from '@/api/project/project.js'
|
|
||||||
import tableComp from "@/components/restful/table.vue"
|
|
||||||
|
|
||||||
const rows = ref([])
|
import table from '@/components/restful/table.vue'
|
||||||
const getProjectListOk = ref(false)
|
import operation from '@/views/project/operation.vue'
|
||||||
|
import {cachedProject} from '@/stores/project.js'
|
||||||
|
import {useRouter} from 'vue-router'
|
||||||
|
|
||||||
getProjectList({page_no: 0, page_len: 100}).then((response) => {
|
const cachedProject1 = cachedProject()
|
||||||
console.log(response)
|
|
||||||
rows.value = response.data
|
const router = useRouter()
|
||||||
getProjectListOk.value = true
|
|
||||||
}, (err) => {
|
const page = ref('project')
|
||||||
console.log(err)
|
|
||||||
})
|
const row_click_handler = (row, column, event) => {
|
||||||
|
// console.log("project row is clicked:", row)
|
||||||
|
cachedProject1.set(row)
|
||||||
|
const cachePro = cachedProject1.get()
|
||||||
|
console.log('cached project:', cachePro)
|
||||||
|
console.log("router:", router.getRoutes())
|
||||||
|
page.value = 'operation'
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
项目
|
<div v-if="page === 'project'">
|
||||||
<div>
|
<component :is="table" resource_url="/project" :row_click_handler="row_click_handler"></component>
|
||||||
<template v-if="getProjectListOk">
|
</div>
|
||||||
<component :is="tableComp" :rows="rows"></component>
|
<div v-else-if="page === 'operation'">
|
||||||
</template>
|
<component :is="operation" resource_url="/project" :row_click_handler="row_click_handler"></component>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -2,6 +2,8 @@ import { fileURLToPath, URL } from 'node:url'
|
|||||||
|
|
||||||
import { defineConfig } from 'vite'
|
import { defineConfig } from 'vite'
|
||||||
import vue from '@vitejs/plugin-vue'
|
import vue from '@vitejs/plugin-vue'
|
||||||
|
import Icons from 'unplugin-icons/vite'
|
||||||
|
import IconsResolver from 'unplugin-icons/resolver'
|
||||||
import vueDevTools from 'vite-plugin-vue-devtools'
|
import vueDevTools from 'vite-plugin-vue-devtools'
|
||||||
|
|
||||||
import AutoImport from 'unplugin-auto-import/vite'
|
import AutoImport from 'unplugin-auto-import/vite'
|
||||||
@ -18,10 +20,25 @@ export default defineConfig(({ mode, command }) => {
|
|||||||
vue(),
|
vue(),
|
||||||
vueDevTools(),
|
vueDevTools(),
|
||||||
AutoImport({
|
AutoImport({
|
||||||
resolvers: [ElementPlusResolver()],
|
imports: ['vue'],
|
||||||
|
resolvers: [
|
||||||
|
ElementPlusResolver(),
|
||||||
|
IconsResolver({
|
||||||
|
prefix: 'Icon',
|
||||||
|
}),
|
||||||
|
],
|
||||||
}),
|
}),
|
||||||
Components({
|
Components({
|
||||||
resolvers: [ElementPlusResolver()],
|
resolvers: [
|
||||||
|
IconsResolver({
|
||||||
|
enabledCollections: ['ep'],
|
||||||
|
}),
|
||||||
|
ElementPlusResolver(),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
|
||||||
|
Icons({
|
||||||
|
autoInstall: true,
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
resolve: {
|
resolve: {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user