diff --git a/admin/apps/game/model/account.go b/admin/apps/game/model/account.go index 9aab85a..b34312e 100644 --- a/admin/apps/game/model/account.go +++ b/admin/apps/game/model/account.go @@ -12,8 +12,8 @@ func init() { // Account 空表,就是用来兼容资源增删改查公共操作的,实际列举账号等都是走各个项目api拉取 type Account struct { ProjectId int - Account string `name:"账号" json:"account"` - ServerConfId string `name:"区服id" json:"serveId"` + Account string `name:"账号" json:"account" where:"eq"` + ServerConfId string `name:"区服id" json:"serveId" where:"eq"` RoleIds []string `gorm:"type:json;serializer:json" name:"角色id列表" json:"roleIds"` LatestLoginTime time.Time `name:"最近登录时间" json:"latest_login_time"` CreateTime time.Time `name:"创建时间" json:"create_time"` diff --git a/admin/apps/game/model/globalmail.go b/admin/apps/game/model/globalmail.go index f7d0fa1..cdc05d2 100644 --- a/admin/apps/game/model/globalmail.go +++ b/admin/apps/game/model/globalmail.go @@ -18,7 +18,7 @@ type GlobalMail struct { Content string `name:"邮件内容" required:"true"` Attach []*MailAttachItem `gorm:"type:json;serializer:json" name:"邮件附件" type:"items" desc:"搜索道具并点击添加"` - CreatedAt time.Time `readonly:"true"` + CreatedAt time.Time `readonly:"true" where:"range"` } func (lm *GlobalMail) TableName() string { diff --git a/admin/apps/game/model/role.go b/admin/apps/game/model/role.go index a303ea1..156c54c 100644 --- a/admin/apps/game/model/role.go +++ b/admin/apps/game/model/role.go @@ -12,10 +12,10 @@ func init() { // Role 空表,就是用来兼容资源增删改查公共操作的,实际列举账号等都是走各个项目api拉取 type Role struct { ProjectId int - RoleId string `name:"角色ID" json:"roleId"` - Account string `name:"账号" json:"account"` - ServerConfId string `name:"区服id" json:"serverId"` - Name string `name:"名称" json:"roleName"` + RoleId string `name:"角色ID" json:"roleId" where:"eq"` + Account string `name:"账号" json:"account" where:"eq"` + ServerConfId string `name:"区服id" json:"serverId" where:"eq"` + Name string `name:"名称" json:"roleName" where:"eq"` Status string `name:"状态" desc:"离线|在线" json:"status"` Level int `name:"等级" json:"roleLevel"` Profession string `name:"职业" json:"profession"` diff --git a/admin/apps/game/model/whitelist.go b/admin/apps/game/model/whitelist.go index d60c851..27d8fd9 100644 --- a/admin/apps/game/model/whitelist.go +++ b/admin/apps/game/model/whitelist.go @@ -13,11 +13,11 @@ func init() { type WhiteList struct { ID int `gorm:"primarykey" readonly:"true"` ProjectId int `gorm:"uniqueIndex:idx_whitelist"` - ServerConfID string `gorm:"type:varchar(200);uniqueIndex:idx_server" name:"区服id" required:"true" choices:"GetChoiceServers"` + ServerConfID string `gorm:"type:varchar(200);uniqueIndex:idx_server" name:"区服id" required:"true" choices:"GetChoiceServers" where:"eq"` Account string `gorm:"type:varchar(128);uniqueIndex:idx_whitelist" name:"账户" required:"true"` Desc string `name:"描述"` - CreatedAt time.Time `readonly:"true"` + CreatedAt time.Time `readonly:"true" where:"range"` } func (lm *WhiteList) TableName() string { diff --git a/admin/apps/game/server/ctl_common_rest.go b/admin/apps/game/server/ctl_common_rest.go index a5d647f..f3185a4 100644 --- a/admin/apps/game/server/ctl_common_rest.go +++ b/admin/apps/game/server/ctl_common_rest.go @@ -3,6 +3,7 @@ package server import ( "admin/apps/game/model/dto" "admin/internal/context" + stdContext "context" ) func (ctl *controller) CommonList(ctx *context.WebContext, params *dto.CommonListReq, rsp *dto.CommonListRsp) error { @@ -17,7 +18,11 @@ func (ctl *controller) CommonList(ctx *context.WebContext, params *dto.CommonLis func (ctl *controller) CommonPost(ctx *context.WebContext, params *dto.CommonPostReq, rsp *dto.CommonPostRsp) error { projectId, resource := getCtxURIProjectIdAndResource(ctx) - newObj, err := ctl.svc.CommonPost(ctx, projectId, resource, *params.Dto) + + ctx1 := stdContext.WithValue(ctx.Context, "user_id", ctx.Header.UserId) + ctx1 = stdContext.WithValue(ctx1, "user_name", ctx.Header.UserId) + + newObj, err := ctl.svc.CommonPost(ctx1, projectId, resource, *params.Dto) if err != nil { return err } diff --git a/admin/apps/game/server/middleware.go b/admin/apps/game/server/middleware.go index 1e06e27..7a14c6c 100644 --- a/admin/apps/game/server/middleware.go +++ b/admin/apps/game/server/middleware.go @@ -23,6 +23,8 @@ func (srv *Server) CheckToken(ctx *context.WebContext) { return } + ctx.Header.UserName = authRsp.User.NickName + ctx.GinCtx().Set("userInfo", authRsp) return } diff --git a/admin/apps/game/server/route.go b/admin/apps/game/server/route.go index 93f27e3..3096018 100644 --- a/admin/apps/game/server/route.go +++ b/admin/apps/game/server/route.go @@ -6,6 +6,8 @@ import ( ) func (srv *Server) Route(engine *web.Engine) { + engine.Use(srv.CheckToken) + apiGroup := engine.Group("/api", "") { diff --git a/admin/apps/game/service/service.go b/admin/apps/game/service/service.go index a14bb7d..39f60e4 100644 --- a/admin/apps/game/service/service.go +++ b/admin/apps/game/service/service.go @@ -6,6 +6,7 @@ import ( "admin/apps/game/model/dto" "admin/internal/consts" "admin/internal/errcode" + "admin/internal/event" "context" "encoding/json" "gorm.io/gorm" @@ -59,18 +60,61 @@ func (svc *Service) CommonPost(ctx context.Context, projectId int, resourceName if resourceName != consts.ResourcesName_Project { params["ProjectId"] = projectId } - return svc.resourceSvc.Create(projectId, resourceName, params) + + values, err := svc.resourceSvc.Create(projectId, resourceName, params) + + userId := ctx.Value("user_id").(int) + userName := ctx.Value("user_name").(string) + + event.GetMgrInstance().Publish(event.EventTopic_UserExecute, &event.EventPayload_UserExecute{ + UserId: userId, + UserName: userName, + ProjectId: projectId, + Resource: resourceName, + Method: "新增", + NewData: params, + }) + + return values, err } func (svc *Service) CommonPut(ctx context.Context, projectId int, resourceName string, params dto.CommonDtoValues) error { if resourceName != consts.ResourcesName_Project { params["ProjectId"] = projectId } - return svc.resourceSvc.Edit(projectId, resourceName, params) + err := svc.resourceSvc.Edit(projectId, resourceName, params) + + userId := ctx.Value("user_id").(int) + userName := ctx.Value("user_name").(string) + + event.GetMgrInstance().Publish(event.EventTopic_UserExecute, &event.EventPayload_UserExecute{ + UserId: userId, + UserName: userName, + ProjectId: projectId, + Resource: resourceName, + Method: "编辑", + NewData: params, + }) + + return err } func (svc *Service) CommonDelete(ctx context.Context, projectId int, resourceName string, id int) error { - return svc.resourceSvc.Delete(projectId, resourceName, id) + err := svc.resourceSvc.Delete(projectId, resourceName, id) + + userId := ctx.Value("user_id").(int) + userName := ctx.Value("user_name").(string) + + event.GetMgrInstance().Publish(event.EventTopic_UserExecute, &event.EventPayload_UserExecute{ + UserId: userId, + UserName: userName, + ProjectId: projectId, + Resource: resourceName, + Method: "删除", + NewData: id, + }) + + return err } func (svc *Service) GetSupportResourcesList(permissions []string) []*api.ResourceInitInfo { diff --git a/admin/apps/user/api/api_user.go b/admin/apps/user/api/api_user.go index fc16cf9..46b1556 100644 --- a/admin/apps/user/api/api_user.go +++ b/admin/apps/user/api/api_user.go @@ -24,6 +24,7 @@ type AuthReq struct { type UserInfo struct { UserId int `json:"user_id"` + UserName string `json:"user_name"` NickName string `json:"nick_name"` Icon string `json:"icon"` Character string `json:"character"` diff --git a/admin/apps/user/model/history.go b/admin/apps/user/model/history.go new file mode 100644 index 0000000..6436e4a --- /dev/null +++ b/admin/apps/user/model/history.go @@ -0,0 +1,35 @@ +package model + +import ( + "admin/internal/db" + "admin/internal/global" + "time" +) + +func init() { + db.RegisterTableModels(History{}) +} + +// History 用户执行历史 +type History struct { + ID int `gorm:"primarykey" readonly:"true"` + UserId int + UserName string + ProjectId int + Resource string + Method string + Data string `gorm:"type:longtext"` + CreateTime time.Time +} + +func (m *History) TableName() string { + return "history" +} + +func (m *History) GetId() int { + return m.ID +} + +func (m *History) Create() error { + return global.GLOB_DB.Create(m).Error +} diff --git a/admin/apps/user/server/server.go b/admin/apps/user/server/server.go index 5280a6f..2adad5c 100644 --- a/admin/apps/user/server/server.go +++ b/admin/apps/user/server/server.go @@ -1,6 +1,12 @@ package server -import "admin/apps/user/service" +import ( + "admin/apps/user/model" + "admin/apps/user/service" + "admin/internal/event" + "admin/lib/xlog" + "encoding/json" +) type Server struct { svc *service.Service @@ -13,3 +19,28 @@ func New(svc *service.Service) *Server { ctl: newController(svc), } } + +func (srv *Server) jobsSubscribe() { + event.GetMgrInstance().Subscribe("user", event.EventTopic_UserExecute, srv.subscriberHandlerUserExecute) +} + +func (srv *Server) subscriberHandlerUserExecute(msg *event.Msg) { + po := new(model.History) + msgHistory := &event.EventPayload_UserExecute{} + err := json.Unmarshal(msg.Payload, msgHistory) + if err != nil { + xlog.Errorf("unmarshal msg(%+v) err:%v", string(msg.Payload), err) + } + + po.UserId = msgHistory.UserId + po.UserName = msgHistory.UserName + po.ProjectId = msgHistory.ProjectId + po.Resource = msgHistory.Resource + po.Method = msgHistory.Method + po.Data = string(msg.Payload) + + err = po.Create() + if err != nil { + xlog.Errorf("create user execute(%+v) err:%v", string(msg.Payload), err) + } +} diff --git a/admin/apps/user/service/service_user.go b/admin/apps/user/service/service_user.go index 80bfd80..2b194b9 100644 --- a/admin/apps/user/service/service_user.go +++ b/admin/apps/user/service/service_user.go @@ -40,6 +40,7 @@ func (svc *Service) Auth(ctx context.Context, req *apiUser.AuthReq) (*apiUser.Au } rsp.User = &apiUser.UserInfo{ UserId: info.User.UserId, + UserName: info.User.NickName, NickName: info.User.NickName, Icon: info.User.Icon, Character: info.User.Character, diff --git a/admin/internal/context/ctx_web.go b/admin/internal/context/ctx_web.go index 6970e54..8bf413f 100644 --- a/admin/internal/context/ctx_web.go +++ b/admin/internal/context/ctx_web.go @@ -9,9 +9,10 @@ import ( ) type WebHeader struct { - UserId int `json:"UserId"` // 用户id,会与下面token解析出用户id做匹配校验 - Token string `json:"Token"` // jwt token,内置一些信息 - Ip string `json:"IP"` + UserId int `json:"UserId"` // 用户id,会与下面token解析出用户id做匹配校验 + Token string `json:"Token"` // jwt token,内置一些信息 + Ip string `json:"IP"` + UserName string `json:"-"` } type WebContext struct { diff --git a/admin/internal/event/event.go b/admin/internal/event/event.go new file mode 100644 index 0000000..a51390d --- /dev/null +++ b/admin/internal/event/event.go @@ -0,0 +1,15 @@ +package event + +import "admin/lib/eventmgr" + +type Msg = eventmgr.Msg + +var manager *eventmgr.Mgr + +func init() { + manager = eventmgr.NewMgr() +} + +func GetMgrInstance() *eventmgr.Mgr { + return manager +} diff --git a/admin/internal/event/topic.go b/admin/internal/event/topic.go new file mode 100644 index 0000000..9b7f16c --- /dev/null +++ b/admin/internal/event/topic.go @@ -0,0 +1,15 @@ +package event + +const ( + EventTopic_UserExecute = "user.execute" +) + +type EventPayload_UserExecute struct { + UserId int `json:"user_id"` + UserName string `json:"user_name"` + ProjectId int `json:"project_id"` + Resource string `json:"resource"` + Method string `json:"method"` + OldData any `json:"old_data"` + NewData any `json:"new_data"` +} diff --git a/admin/lib/eventmgr/event.go b/admin/lib/eventmgr/event.go new file mode 100644 index 0000000..938ae11 --- /dev/null +++ b/admin/lib/eventmgr/event.go @@ -0,0 +1,66 @@ +package eventmgr + +import ( + "admin/lib/xlog" + "encoding/json" + "runtime" +) + +type Msg struct { + Event string + Payload []byte +} + +type subscriber struct { + name string + topic string + handler func(*Msg) +} + +type Mgr struct { + subscribers []*subscriber + broker chan *Msg +} + +func NewMgr() *Mgr { + mgr := &Mgr{ + subscribers: make([]*subscriber, 0), + broker: make(chan *Msg, 1024), + } + mgr.start() + return mgr +} + +func (m *Mgr) start() { + for i := 0; i < runtime.NumCPU(); i++ { + go func() { + for { + select { + case msg := <-m.broker: + for _, sub := range m.subscribers { + if sub.topic == msg.Event { + sub.handler(msg) + } + } + } + } + }() + } +} + +func (m *Mgr) Subscribe(name string, topic string, handler func(*Msg)) { + m.subscribers = append(m.subscribers, &subscriber{name: name, topic: topic, handler: handler}) +} + +func (m *Mgr) Publish(event string, payload any) { + payloadBin, err := json.Marshal(payload) + if err != nil { + panic(err) + } + msg := &Msg{Event: event, Payload: payloadBin} + select { + case m.broker <- msg: + default: + xlog.Errorf("publish event:%v broker is full", event) + } +} diff --git a/admin/uniugm b/admin/uniugm index 7ba7d54..1ac481a 100644 Binary files a/admin/uniugm and b/admin/uniugm differ diff --git a/ui/src/components/restful/table.vue b/ui/src/components/restful/table.vue index 6b19e0a..7804e0d 100644 --- a/ui/src/components/restful/table.vue +++ b/ui/src/components/restful/table.vue @@ -304,8 +304,17 @@ const handleQueryItem = (itemQueryStr) => {