add exec history
This commit is contained in:
parent
c65851b018
commit
e2612f16b4
@ -12,8 +12,8 @@ func init() {
|
|||||||
// Account 空表,就是用来兼容资源增删改查公共操作的,实际列举账号等都是走各个项目api拉取
|
// Account 空表,就是用来兼容资源增删改查公共操作的,实际列举账号等都是走各个项目api拉取
|
||||||
type Account struct {
|
type Account struct {
|
||||||
ProjectId int
|
ProjectId int
|
||||||
Account string `name:"账号" json:"account"`
|
Account string `name:"账号" json:"account" where:"eq"`
|
||||||
ServerConfId string `name:"区服id" json:"serveId"`
|
ServerConfId string `name:"区服id" json:"serveId" where:"eq"`
|
||||||
RoleIds []string `gorm:"type:json;serializer:json" name:"角色id列表" json:"roleIds"`
|
RoleIds []string `gorm:"type:json;serializer:json" name:"角色id列表" json:"roleIds"`
|
||||||
LatestLoginTime time.Time `name:"最近登录时间" json:"latest_login_time"`
|
LatestLoginTime time.Time `name:"最近登录时间" json:"latest_login_time"`
|
||||||
CreateTime time.Time `name:"创建时间" json:"create_time"`
|
CreateTime time.Time `name:"创建时间" json:"create_time"`
|
||||||
|
@ -18,7 +18,7 @@ type GlobalMail struct {
|
|||||||
Content string `name:"邮件内容" required:"true"`
|
Content string `name:"邮件内容" required:"true"`
|
||||||
Attach []*MailAttachItem `gorm:"type:json;serializer:json" name:"邮件附件" type:"items" desc:"搜索道具并点击添加"`
|
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 {
|
func (lm *GlobalMail) TableName() string {
|
||||||
|
@ -12,10 +12,10 @@ func init() {
|
|||||||
// Role 空表,就是用来兼容资源增删改查公共操作的,实际列举账号等都是走各个项目api拉取
|
// Role 空表,就是用来兼容资源增删改查公共操作的,实际列举账号等都是走各个项目api拉取
|
||||||
type Role struct {
|
type Role struct {
|
||||||
ProjectId int
|
ProjectId int
|
||||||
RoleId string `name:"角色ID" json:"roleId"`
|
RoleId string `name:"角色ID" json:"roleId" where:"eq"`
|
||||||
Account string `name:"账号" json:"account"`
|
Account string `name:"账号" json:"account" where:"eq"`
|
||||||
ServerConfId string `name:"区服id" json:"serverId"`
|
ServerConfId string `name:"区服id" json:"serverId" where:"eq"`
|
||||||
Name string `name:"名称" json:"roleName"`
|
Name string `name:"名称" json:"roleName" where:"eq"`
|
||||||
Status string `name:"状态" desc:"离线|在线" json:"status"`
|
Status string `name:"状态" desc:"离线|在线" json:"status"`
|
||||||
Level int `name:"等级" json:"roleLevel"`
|
Level int `name:"等级" json:"roleLevel"`
|
||||||
Profession string `name:"职业" json:"profession"`
|
Profession string `name:"职业" json:"profession"`
|
||||||
|
@ -13,11 +13,11 @@ func init() {
|
|||||||
type WhiteList struct {
|
type WhiteList struct {
|
||||||
ID int `gorm:"primarykey" readonly:"true"`
|
ID int `gorm:"primarykey" readonly:"true"`
|
||||||
ProjectId int `gorm:"uniqueIndex:idx_whitelist"`
|
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"`
|
Account string `gorm:"type:varchar(128);uniqueIndex:idx_whitelist" name:"账户" required:"true"`
|
||||||
Desc string `name:"描述"`
|
Desc string `name:"描述"`
|
||||||
|
|
||||||
CreatedAt time.Time `readonly:"true"`
|
CreatedAt time.Time `readonly:"true" where:"range"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lm *WhiteList) TableName() string {
|
func (lm *WhiteList) TableName() string {
|
||||||
|
@ -3,6 +3,7 @@ package server
|
|||||||
import (
|
import (
|
||||||
"admin/apps/game/model/dto"
|
"admin/apps/game/model/dto"
|
||||||
"admin/internal/context"
|
"admin/internal/context"
|
||||||
|
stdContext "context"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (ctl *controller) CommonList(ctx *context.WebContext, params *dto.CommonListReq, rsp *dto.CommonListRsp) error {
|
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 {
|
func (ctl *controller) CommonPost(ctx *context.WebContext, params *dto.CommonPostReq, rsp *dto.CommonPostRsp) error {
|
||||||
projectId, resource := getCtxURIProjectIdAndResource(ctx)
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,8 @@ func (srv *Server) CheckToken(ctx *context.WebContext) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctx.Header.UserName = authRsp.User.NickName
|
||||||
|
|
||||||
ctx.GinCtx().Set("userInfo", authRsp)
|
ctx.GinCtx().Set("userInfo", authRsp)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (srv *Server) Route(engine *web.Engine) {
|
func (srv *Server) Route(engine *web.Engine) {
|
||||||
|
engine.Use(srv.CheckToken)
|
||||||
|
|
||||||
apiGroup := engine.Group("/api", "")
|
apiGroup := engine.Group("/api", "")
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"admin/apps/game/model/dto"
|
"admin/apps/game/model/dto"
|
||||||
"admin/internal/consts"
|
"admin/internal/consts"
|
||||||
"admin/internal/errcode"
|
"admin/internal/errcode"
|
||||||
|
"admin/internal/event"
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
@ -59,18 +60,61 @@ func (svc *Service) CommonPost(ctx context.Context, projectId int, resourceName
|
|||||||
if resourceName != consts.ResourcesName_Project {
|
if resourceName != consts.ResourcesName_Project {
|
||||||
params["ProjectId"] = projectId
|
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 {
|
func (svc *Service) CommonPut(ctx context.Context, projectId int, resourceName string, params dto.CommonDtoValues) error {
|
||||||
if resourceName != consts.ResourcesName_Project {
|
if resourceName != consts.ResourcesName_Project {
|
||||||
params["ProjectId"] = projectId
|
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 {
|
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 {
|
func (svc *Service) GetSupportResourcesList(permissions []string) []*api.ResourceInitInfo {
|
||||||
|
@ -24,6 +24,7 @@ type AuthReq struct {
|
|||||||
|
|
||||||
type UserInfo struct {
|
type UserInfo struct {
|
||||||
UserId int `json:"user_id"`
|
UserId int `json:"user_id"`
|
||||||
|
UserName string `json:"user_name"`
|
||||||
NickName string `json:"nick_name"`
|
NickName string `json:"nick_name"`
|
||||||
Icon string `json:"icon"`
|
Icon string `json:"icon"`
|
||||||
Character string `json:"character"`
|
Character string `json:"character"`
|
||||||
|
35
admin/apps/user/model/history.go
Normal file
35
admin/apps/user/model/history.go
Normal file
@ -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
|
||||||
|
}
|
@ -1,6 +1,12 @@
|
|||||||
package server
|
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 {
|
type Server struct {
|
||||||
svc *service.Service
|
svc *service.Service
|
||||||
@ -13,3 +19,28 @@ func New(svc *service.Service) *Server {
|
|||||||
ctl: newController(svc),
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -40,6 +40,7 @@ func (svc *Service) Auth(ctx context.Context, req *apiUser.AuthReq) (*apiUser.Au
|
|||||||
}
|
}
|
||||||
rsp.User = &apiUser.UserInfo{
|
rsp.User = &apiUser.UserInfo{
|
||||||
UserId: info.User.UserId,
|
UserId: info.User.UserId,
|
||||||
|
UserName: info.User.NickName,
|
||||||
NickName: info.User.NickName,
|
NickName: info.User.NickName,
|
||||||
Icon: info.User.Icon,
|
Icon: info.User.Icon,
|
||||||
Character: info.User.Character,
|
Character: info.User.Character,
|
||||||
|
@ -9,9 +9,10 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type WebHeader struct {
|
type WebHeader struct {
|
||||||
UserId int `json:"UserId"` // 用户id,会与下面token解析出用户id做匹配校验
|
UserId int `json:"UserId"` // 用户id,会与下面token解析出用户id做匹配校验
|
||||||
Token string `json:"Token"` // jwt token,内置一些信息
|
Token string `json:"Token"` // jwt token,内置一些信息
|
||||||
Ip string `json:"IP"`
|
Ip string `json:"IP"`
|
||||||
|
UserName string `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type WebContext struct {
|
type WebContext struct {
|
||||||
|
15
admin/internal/event/event.go
Normal file
15
admin/internal/event/event.go
Normal file
@ -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
|
||||||
|
}
|
15
admin/internal/event/topic.go
Normal file
15
admin/internal/event/topic.go
Normal file
@ -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"`
|
||||||
|
}
|
66
admin/lib/eventmgr/event.go
Normal file
66
admin/lib/eventmgr/event.go
Normal file
@ -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)
|
||||||
|
}
|
||||||
|
}
|
BIN
admin/uniugm
BIN
admin/uniugm
Binary file not shown.
@ -304,8 +304,17 @@ const handleQueryItem = (itemQueryStr) => {
|
|||||||
</el-col>
|
</el-col>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<el-input v-model="fieldDescInfo.value1"
|
<el-col :span="calcElColSpan">
|
||||||
:placeholder="(fieldDescInfo.name + fieldDescInfo.whereDesc)" style="width: 150px"></el-input>
|
<el-select v-model="fieldDescInfo.value1" :placeholder="(fieldDescInfo.multi_choice === true ? '--多选--' : '--单选--')"
|
||||||
|
style="width: 150px"
|
||||||
|
filterable v-if="(fieldDescInfo.choices.length > 0)">
|
||||||
|
<el-option v-for="choice in fieldDescInfo.choices" :key="choice.value" :label="choice.desc"
|
||||||
|
:value="choice.value"></el-option>
|
||||||
|
</el-select>
|
||||||
|
<el-input v-model="fieldDescInfo.value1"
|
||||||
|
:placeholder="(fieldDescInfo.name + fieldDescInfo.whereDesc)"
|
||||||
|
style="width: 150px" v-else></el-input>
|
||||||
|
</el-col>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
<el-col :span="calcElColSpan">
|
<el-col :span="calcElColSpan">
|
||||||
|
Loading…
x
Reference in New Issue
Block a user