From 44372acdef12568c3a3a60a2c41e2857b5ad9b45 Mon Sep 17 00:00:00 2001 From: likun <906102152@qq.com> Date: Mon, 19 May 2025 17:51:09 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E7=94=A8=E6=88=B7=E6=89=A7?= =?UTF-8?q?=E8=A1=8C=E5=8E=86=E5=8F=B2=E5=B1=95=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- admin/apps/game/domain/comm_resource.go | 89 +++++-- admin/apps/game/domain/entity/cdkey.go | 9 +- .../apps/game/domain/projects/smdl/server.go | 4 + admin/apps/game/domain/repo/comm_resource.go | 10 + admin/apps/game/model/ban.go | 4 + admin/apps/game/model/cdkey.go | 4 + admin/apps/game/model/globalmail.go | 4 + admin/apps/game/model/item_bag.go | 4 + admin/apps/game/model/project.go | 4 + admin/apps/game/model/rolemail.go | 4 + admin/apps/game/model/server.go | 4 + admin/apps/game/model/support_account.go | 4 + admin/apps/game/model/whitelist.go | 4 + admin/apps/game/service/service.go | 148 ++++++++---- admin/apps/user/model/history.go | 70 +++++- admin/apps/user/server/ctl_user.go | 9 + admin/apps/user/server/route.go | 2 +- admin/apps/user/server/server.go | 30 ++- admin/apps/user/service/service_user.go | 37 +++ admin/internal/consts/consts.go | 4 + admin/internal/event/topic.go | 21 +- admin/internal/model/dto/common.go | 11 + admin/internal/model/dto/msg_project.go | 1 + admin/internal/model/dto/msg_user.go | 15 ++ ui/src/api/sys.js | 18 ++ ui/src/components/restful/tableUser.vue | 52 +++++ ui/src/components/user/history.vue | 219 ++++++++++++++++++ ui/src/views/Home.vue | 3 + ui/src/views/user/history.vue | 4 +- ui/src/views/user/user.vue | 13 +- 30 files changed, 702 insertions(+), 103 deletions(-) create mode 100644 ui/src/components/user/history.vue diff --git a/admin/apps/game/domain/comm_resource.go b/admin/apps/game/domain/comm_resource.go index 06867ee..6e0571c 100644 --- a/admin/apps/game/domain/comm_resource.go +++ b/admin/apps/game/domain/comm_resource.go @@ -16,6 +16,7 @@ import ( "fmt" "gorm.io/gorm" "reflect" + "strconv" "strings" "time" ) @@ -153,13 +154,13 @@ func (svc *CommonResourceService) GetById(projectId int, resource string, id int return fieldsDescInfo, et.ToCommonDto(), et, find, nil } -func (svc *CommonResourceService) Create(projectId int, resource string, dtoObj dto2.CommonDtoValues) (dto2.CommonDtoValues, error) { +func (svc *CommonResourceService) Create(projectId int, resource string, dtoObj dto2.CommonDtoValues) (*entity.Project, dto2.CommonDtoValues, error) { _, projectEt, find, err := svc.projectRepo.GetById(projectId) if err != nil { - return nil, err + return projectEt, nil, err } if resource != consts.ResourcesName_Project && !find { - return nil, errcode.New(errcode.ServerError, "not found project %v db data", projectId) + return projectEt, nil, errcode.New(errcode.ServerError, "not found project %v db data", projectId) } createOne := func(obj dto2.CommonDtoValues) (dto2.CommonDtoValues, error) { @@ -217,53 +218,53 @@ func (svc *CommonResourceService) Create(projectId int, resource string, dtoObj } } } else { - return nil, errcode.New(errcode.ParamsInvalid, "account empty:%+v", dtoObj) + return projectEt, nil, errcode.New(errcode.ParamsInvalid, "account empty:%+v", dtoObj) } } else { newDtoObj, err = createOne(dtoObj) } - return newDtoObj, err + return projectEt, newDtoObj, err } -func (svc *CommonResourceService) Edit(projectId int, resource string, dtoObj dto2.CommonDtoValues) error { +func (svc *CommonResourceService) Edit(projectId int, resource string, dtoObj dto2.CommonDtoValues) (*entity.Project, error) { _, projectEt, find, err := svc.projectRepo.GetById(projectId) if err != nil { - return err + return projectEt, err } if resource != consts.ResourcesName_Project && !find { - return errcode.New(errcode.ServerError, "not found project %v db data", projectId) + return projectEt, errcode.New(errcode.ServerError, "not found project %v db data", projectId) } err = findCommResourceRepo(resource).Repo.Edit(projectEt, dtoObj) if err != nil { - return err + return projectEt, err } // 执行各个项目特定的钩子方法 if hook, ok := projects.GetProjectResourceHook(projectEt, resource).(projects.IPostResourceOpEditHook); ok { err = hook.Edit(projectEt, resource, dtoObj) if err != nil { - return err + return projectEt, err } - return nil + return projectEt, nil } - return nil + return projectEt, nil } -func (svc *CommonResourceService) Delete(projectId int, resource string, id int) (*entity.CommonResource, error) { +func (svc *CommonResourceService) Delete(projectId int, resource string, id int) (*entity.Project, *entity.CommonResource, error) { _, projectEt, find, err := svc.projectRepo.GetById(projectId) if err != nil { - return nil, err + return projectEt, nil, err } if resource != consts.ResourcesName_Project && !find { - return nil, errcode.New(errcode.ServerError, "not found project %v db data", projectId) + return projectEt, nil, errcode.New(errcode.ServerError, "not found project %v db data", projectId) } oldEt, find, err := findCommResourceRepo(resource).Repo.Delete(projectEt, id) if err != nil { - return nil, err + return projectEt, nil, err } // 执行各个项目特定的钩子方法 @@ -271,27 +272,67 @@ func (svc *CommonResourceService) Delete(projectId int, resource string, id int) if hook, ok := projects.GetProjectResourceHook(projectEt, resource).(projects.IPostResourceOpDeleteHook); ok { err = hook.Delete(projectEt, resource, oldEt.ToCommonDto()) if err != nil { - return oldEt, err + return projectEt, oldEt, err } - return oldEt, nil + return projectEt, oldEt, nil } } - return oldEt, nil + return projectEt, oldEt, nil } -func (svc *CommonResourceService) RowsSelection(projectId int, resourceName string, params *dto2.CommonRowsSelectionReq) (*dto2.CommonRowsSelectionRsp, error) { +func (svc *CommonResourceService) RowsSelection(projectId int, resourceName string, params *dto2.CommonRowsSelectionReq) (*entity.Project, *dto2.CommonRowsSelectionRsp, error) { _, projectEt, find, err := svc.projectRepo.GetById(projectId) if err != nil { - return nil, err + return projectEt, nil, err } if resourceName != consts.ResourcesName_Project && !find { - return nil, errcode.New(errcode.ServerError, "not found project %v db data", projectId) + return projectEt, nil, errcode.New(errcode.ServerError, "not found project %v db data", projectId) } if hook, ok := projects.GetProjectResourceHook(projectEt, resourceName).(projects.IPostResourceOpRowsHook); ok { - return hook.RowsSelection(projectEt, resourceName, params.BtnKey, params.Rows) + rsp, err := hook.RowsSelection(projectEt, resourceName, params.BtnKey, params.Rows) + return projectEt, rsp, err } - return nil, nil + return projectEt, nil, nil +} + +func (svc *CommonResourceService) GetResourceKeyByDto(resource string, dtoObj []dto2.CommonDtoValues) (string, string) { + resourceInfo := findCommResourceRepo(resource) + desc := resourceInfo.Desc + etList := resourceInfo.Repo.MakeEntitiesByDtoList(dtoObj) + keyList := make([]string, 0, len(dtoObj)) + for _, et := range etList { + po := et.Po.(model.IModel) + method := reflect.ValueOf(po).MethodByName("GetShowKey") + var key string + if !method.IsValid() { + key = strconv.Itoa(po.GetId()) + } else { + rets := method.Call([]reflect.Value{}) + key = rets[0].Interface().(string) + } + + keyList = append(keyList, key) + } + if len(keyList) > 1 { + return desc, "[" + strings.Join(keyList, ",") + "]" + } + return desc, strings.Join(keyList, ",") +} + +func (svc *CommonResourceService) GetResourceSpecBtnKey(resource string, btnKey string) *api.ResourceBtnInfo { + resourceInfo := findCommResourceRepo(resource) + for _, v := range resourceInfo.GlobalBtns { + if v.Key == btnKey { + return v + } + } + for _, v := range resourceInfo.RowBtns { + if v.Key == btnKey { + return v + } + } + return nil } func (svc *CommonResourceService) GetSupportResourcesList(permissions []string) []*api.ResourceInitInfo { diff --git a/admin/apps/game/domain/entity/cdkey.go b/admin/apps/game/domain/entity/cdkey.go index 65bf435..70b74ee 100644 --- a/admin/apps/game/domain/entity/cdkey.go +++ b/admin/apps/game/domain/entity/cdkey.go @@ -9,8 +9,6 @@ import ( "time" ) -var MaxKeyNum = 100000 // 每个批次直接搞10w个,不然运营想补加码,算法又要一开始定好数量 - type CDKey struct { Po *model.CDKey } @@ -33,7 +31,12 @@ func (c *CDKey) GenerateKeys() []string { if c.IsGlobalType() { return []string{c.Po.Code} } - return cdkey.GenerateAll(c.Po.ID, MaxKeyNum)[:c.Po.CodeNum] + codeList := make([]string, 0, c.Po.CodeNum) + for i := 0; i < c.Po.CodeNum; i++ { + codeList = append(codeList, cdkey.GenerateOne(c.Po.ID, consts.CDKeyBatchMaxKeyNum, i)) + } + return codeList + //return cdkey.GenerateAll(c.Po.ID, consts.CDKeyBatchMaxKeyNum)[:c.Po.CodeNum] } func (c *CDKey) AddCount(delta int) { diff --git a/admin/apps/game/domain/projects/smdl/server.go b/admin/apps/game/domain/projects/smdl/server.go index ce0b7bd..2b0c400 100644 --- a/admin/apps/game/domain/projects/smdl/server.go +++ b/admin/apps/game/domain/projects/smdl/server.go @@ -10,6 +10,7 @@ import ( dto2 "admin/internal/model/dto" "admin/lib/xlog" "fmt" + "strings" ) type ServerHook struct { @@ -71,7 +72,9 @@ func (hook *ServerHook) RowsSelection(projectInfo *entity.Project, resource stri return nil, err } + opServers := make([]string, 0) opHandler := func(serverRunningInfo *internal.ServerInfo) error { + opServers = append(opServers, serverRunningInfo.ServerId) switch btnKey { case consts.BtnKeyGlobal_Server_UpAll, consts.BtnKeyRow_Server_Up: err := serverRunningInfo.Up(apiAddr) @@ -137,6 +140,7 @@ func (hook *ServerHook) RowsSelection(projectInfo *entity.Project, resource stri return &dto2.CommonRowsSelectionRsp{ Msg: fmt.Sprintf("执行%v操作成功!", msg), NeedRefresh: true, + ShortDesc: "[" + strings.Join(opServers, ",") + "]", }, nil } diff --git a/admin/apps/game/domain/repo/comm_resource.go b/admin/apps/game/domain/repo/comm_resource.go index 58e79a4..0c09200 100644 --- a/admin/apps/game/domain/repo/comm_resource.go +++ b/admin/apps/game/domain/repo/comm_resource.go @@ -29,6 +29,7 @@ type ICommonResourceRepo interface { Delete(projectEt *entity.Project, id int) (*entity.CommonResource, bool, error) ListPagination(whereSql string, whereArgs []any, f func(po model.IModel)) error UpdateClearDelayInvokeCreateHookFieldN(id int) error + MakeEntitiesByDtoList(dtoList []dto2.CommonDtoValues) []*entity.CommonResource } func NewCommonResourceRepo(db *gorm.DB, poTemplate model.IModel) ICommonResourceRepo { @@ -199,6 +200,15 @@ func (repo *commonResourceRepoImpl) UpdateClearDelayInvokeCreateHookFieldN(id in return nil } +func (repo *commonResourceRepoImpl) MakeEntitiesByDtoList(dtoList []dto2.CommonDtoValues) []*entity.CommonResource { + list := make([]*entity.CommonResource, 0, len(dtoList)) + for _, v := range dtoList { + po := repo.makeEmptyPo() + list = append(list, (&entity.CommonResource{}).FromPo(po).FromDto(v)) + } + return list +} + func (repo *commonResourceRepoImpl) makeEmptyPo() model.IModel { return reflect.New(reflect.TypeOf(repo.poTemplate).Elem()).Interface().(model.IModel) } diff --git a/admin/apps/game/model/ban.go b/admin/apps/game/model/ban.go index 5d5f333..420ecbb 100644 --- a/admin/apps/game/model/ban.go +++ b/admin/apps/game/model/ban.go @@ -34,6 +34,10 @@ func (m *Ban) GetId() int { return m.ID } +func (m *Ban) GetShowKey() string { + return m.Value +} + func (m *Ban) GetServerConfIDChoices(project *Project) []*dto.CommonDtoFieldChoice { return getChoiceServers(project) } diff --git a/admin/apps/game/model/cdkey.go b/admin/apps/game/model/cdkey.go index d23919c..3db57f6 100644 --- a/admin/apps/game/model/cdkey.go +++ b/admin/apps/game/model/cdkey.go @@ -36,6 +36,10 @@ func (m *CDKey) GetId() int { return m.ID } +func (m *CDKey) GetShowKey() string { + return m.Name +} + func (m *CDKey) GetCodeTypeChoices(project *Project) []*dto.CommonDtoFieldChoice { return []*dto.CommonDtoFieldChoice{ {Desc: "一码通用", Value: consts.CDKeyType_Global}, diff --git a/admin/apps/game/model/globalmail.go b/admin/apps/game/model/globalmail.go index dbcaefd..c4956b2 100644 --- a/admin/apps/game/model/globalmail.go +++ b/admin/apps/game/model/globalmail.go @@ -32,6 +32,10 @@ func (lm *GlobalMail) TableName() string { return "mail_global" } +func (m *GlobalMail) GetShowKey() string { + return m.Title +} + func (m *GlobalMail) GetId() int { return m.ID } diff --git a/admin/apps/game/model/item_bag.go b/admin/apps/game/model/item_bag.go index d2e6d88..be63b8a 100644 --- a/admin/apps/game/model/item_bag.go +++ b/admin/apps/game/model/item_bag.go @@ -31,6 +31,10 @@ func (m *ItemBag) GetId() int { return m.ID } +func (m *ItemBag) GetShowKey() string { + return m.Name +} + func (m *ItemBag) GetChoiceServers(project *Project) []*dto.CommonDtoFieldChoice { return getChoiceServers(project) } diff --git a/admin/apps/game/model/project.go b/admin/apps/game/model/project.go index 32a24af..52991ec 100644 --- a/admin/apps/game/model/project.go +++ b/admin/apps/game/model/project.go @@ -39,6 +39,10 @@ func (m *Project) GetId() int { return m.ID } +func (m *Project) GetShowKey() string { + return m.Name +} + func (m *Project) GetProjectChoices(_ *Project) []*dto.CommonDtoFieldChoice { return []*dto.CommonDtoFieldChoice{ {Desc: "神魔大陆", Value: consts.RegisteredProjectId_shenmodalu, Type: 0}, diff --git a/admin/apps/game/model/rolemail.go b/admin/apps/game/model/rolemail.go index 0e7a4d6..1d5b7c8 100644 --- a/admin/apps/game/model/rolemail.go +++ b/admin/apps/game/model/rolemail.go @@ -38,6 +38,10 @@ func (m *RoleMail) GetId() int { return m.ID } +func (m *RoleMail) GetShowKey() string { + return m.Title +} + func (m *RoleMail) GetChoiceServers(project *Project) []*dto.CommonDtoFieldChoice { return getChoiceServers(project) } diff --git a/admin/apps/game/model/server.go b/admin/apps/game/model/server.go index 195aae1..f4c6213 100644 --- a/admin/apps/game/model/server.go +++ b/admin/apps/game/model/server.go @@ -40,6 +40,10 @@ func (m *Server) GetId() int { return m.ID } +func (m *Server) GetShowKey() string { + return m.ServerConfID +} + func (m *Server) ListByProjectId(projectId int) ([]*Server, error) { list := make([]*Server, 0) err := global.GLOB_DB.Where("project_id=?", projectId).Find(&list).Error diff --git a/admin/apps/game/model/support_account.go b/admin/apps/game/model/support_account.go index 33b5641..60fc041 100644 --- a/admin/apps/game/model/support_account.go +++ b/admin/apps/game/model/support_account.go @@ -28,6 +28,10 @@ func (m *SupportAccount) GetId() int { return m.ID } +func (m *SupportAccount) GetShowKey() string { + return m.Account +} + func (m *SupportAccount) GetChoiceServers(project *Project) []*dto.CommonDtoFieldChoice { return getChoiceServers(project) } diff --git a/admin/apps/game/model/whitelist.go b/admin/apps/game/model/whitelist.go index 92ec7a6..75d76be 100644 --- a/admin/apps/game/model/whitelist.go +++ b/admin/apps/game/model/whitelist.go @@ -29,6 +29,10 @@ func (m *WhiteList) GetId() int { return m.ID } +func (m *WhiteList) GetShowKey() string { + return m.Value +} + func (m *WhiteList) GetChoiceServers(project *Project) []*dto.CommonDtoFieldChoice { return getChoiceServers(project) } diff --git a/admin/apps/game/service/service.go b/admin/apps/game/service/service.go index 1cf3bce..7e55257 100644 --- a/admin/apps/game/service/service.go +++ b/admin/apps/game/service/service.go @@ -9,7 +9,6 @@ import ( dto2 "admin/internal/model/dto" "context" "encoding/json" - "fmt" "gorm.io/gorm" ) @@ -70,19 +69,31 @@ func (svc *Service) CommonPost(ctx context.Context, projectId int, resourceName params["ProjectId"] = projectId } - values, err := svc.resourceSvc.Create(projectId, resourceName, params) + project, values, err := svc.resourceSvc.Create(projectId, resourceName, params) + if err != nil { + return nil, err + } userId := ctx.Value("user_id").(int) - userName := ctx.Value("user_name").(string) + //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, - }) + resourceDesc, keyDesc := svc.resourceSvc.GetResourceKeyByDto(resourceName, []dto2.CommonDtoValues{params}) + + evPayload := &event.EventPayload_UserGameExecute{ + UserId: userId, + ProjectId: projectId, + ProjectName: project.Po.Name, + OpResourceType: resourceDesc, + OpResourceGroup: "系统", + OpResourceKey: keyDesc, + Method: "新增", + SrcDataList: []any{params}, + } + if resourceName != consts.ResourcesName_Project { + evPayload.OpResourceGroup = project.Po.Name + } + + event.GetMgrInstance().Publish(event.EventTopic_UserGameExecute, evPayload) return values, err } @@ -91,61 +102,100 @@ func (svc *Service) CommonPut(ctx context.Context, projectId int, resourceName s if resourceName != consts.ResourcesName_Project { params["ProjectId"] = projectId } - 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 { - deletedEt, err := svc.resourceSvc.Delete(projectId, resourceName, id) + project, err := svc.resourceSvc.Edit(projectId, resourceName, params) if err != nil { return err } userId := ctx.Value("user_id").(int) - userName := ctx.Value("user_name").(string) + //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: deletedEt.ToCommonDto(), - }) + resourceDesc, keyDesc := svc.resourceSvc.GetResourceKeyByDto(resourceName, []dto2.CommonDtoValues{params}) + + evPayload := &event.EventPayload_UserGameExecute{ + UserId: userId, + ProjectId: projectId, + ProjectName: project.Po.Name, + OpResourceType: resourceDesc, + OpResourceGroup: "系统", + OpResourceKey: keyDesc, + Method: "编辑", + SrcDataList: []any{params}, + } + if resourceName != consts.ResourcesName_Project { + evPayload.OpResourceGroup = project.Po.Name + } + + event.GetMgrInstance().Publish(event.EventTopic_UserGameExecute, evPayload) + + return err +} + +func (svc *Service) CommonDelete(ctx context.Context, projectId int, resourceName string, id int) error { + project, deletedEt, err := svc.resourceSvc.Delete(projectId, resourceName, id) + if err != nil { + return err + } + + userId := ctx.Value("user_id").(int) + //userName := ctx.Value("user_name").(string) + + delObj := deletedEt.ToCommonDto() + resourceDesc, keyDesc := svc.resourceSvc.GetResourceKeyByDto(resourceName, []dto2.CommonDtoValues{delObj}) + + evPayload := &event.EventPayload_UserGameExecute{ + UserId: userId, + ProjectId: projectId, + ProjectName: project.Po.Name, + OpResourceType: resourceDesc, + OpResourceGroup: "系统", + OpResourceKey: keyDesc, + Method: "删除", + SrcDataList: []any{delObj}, + } + if resourceName != consts.ResourcesName_Project { + evPayload.OpResourceGroup = project.Po.Name + } + event.GetMgrInstance().Publish(event.EventTopic_UserGameExecute, evPayload) return err } func (svc *Service) CommonRowsSelection(ctx context.Context, projectId int, resourceName string, param *dto2.CommonRowsSelectionReq) (*dto2.CommonRowsSelectionRsp, error) { - rsp, err := svc.resourceSvc.RowsSelection(projectId, resourceName, param) + project, rsp, err := svc.resourceSvc.RowsSelection(projectId, resourceName, param) if err != nil { return rsp, err } userId := ctx.Value("user_id").(int) - userName := ctx.Value("user_name").(string) + //userName := ctx.Value("user_name").(string) - event.GetMgrInstance().Publish(event.EventTopic_UserExecute, &event.EventPayload_UserExecute{ - UserId: userId, - UserName: userName, - ProjectId: projectId, - Resource: resourceName, - Method: fmt.Sprintf("选择行:%v", param.BtnKey), - Any: param, - }) + srcDataList := make([]any, 0, len(param.Rows)) + for _, v := range param.Rows { + srcDataList = append(srcDataList, v) + } + + resourceDesc, keyDesc := svc.resourceSvc.GetResourceKeyByDto(resourceName, param.Rows) + btnInfo := svc.resourceSvc.GetResourceSpecBtnKey(resourceName, param.BtnKey) + + evPayload := &event.EventPayload_UserGameExecute{ + UserId: userId, + ProjectId: projectId, + ProjectName: project.Po.Name, + OpResourceType: resourceDesc, + OpResourceGroup: "系统", + OpResourceKey: keyDesc, + Method: param.BtnKey, + SrcDataList: srcDataList, + } + if btnInfo != nil { + evPayload.Method = btnInfo.Name + } + if resourceName != consts.ResourcesName_Project { + evPayload.OpResourceGroup = project.Po.Name + } + + event.GetMgrInstance().Publish(event.EventTopic_UserGameExecute, evPayload) return rsp, err } diff --git a/admin/apps/user/model/history.go b/admin/apps/user/model/history.go index 9725828..1b8aca3 100644 --- a/admin/apps/user/model/history.go +++ b/admin/apps/user/model/history.go @@ -2,7 +2,9 @@ package model import ( "admin/internal/db" + "admin/internal/errcode" "admin/internal/global" + "strings" "time" ) @@ -12,14 +14,15 @@ func init() { // 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"` - CreatedAt time.Time + ID int `gorm:"primarykey" readonly:"true"` + UserId int `gorm:"index"` + UserName string `gorm:"index"` + OpResourceType string `gorm:"type:varchar(100);index"` // 操作资源类型:项目、角色、用户、封禁等 + OpResourceGroup string `gorm:"type:varchar(100);index"` // 操作资源组名:系统、系统、系统、神魔大陆主播服等 + OpResourceKey string `gorm:"type:varchar(100);index"` // 操作对象名:神魔大陆主播服、qa、chenshun、account123 + Method string `gorm:"type:varchar(100);index"` // 操作方法:新增、修改、删除、一键停服 + DetailInfo string `gorm:"type:longtext"` // 详情,涉及到的对象列表,例如新增就给表行数据 + CreatedAt time.Time } func (m *History) TableName() string { @@ -33,3 +36,54 @@ func (m *History) GetId() int { func (m *History) Create() error { return global.GLOB_DB.Create(m).Error } + +func (m *History) List(pageNo, pageLen int, userId int, opType, opGroup, opKey, method string) ([]*History, int, error) { + if pageNo <= 0 || pageLen <= 0 || pageLen > 1000 { + return nil, 0, errcode.New(errcode.ParamsInvalid, "pageNo or pageLen invalid:%v,%v", pageNo, pageLen) + } + + list := make([]*History, 0) + + whereSqls := make([]string, 0) + whereArgs := make([]any, 0) + + if userId != 0 { + whereSqls = append(whereSqls, "user_id=?") + whereArgs = append(whereArgs, userId) + } + if opType != "" { + whereSqls = append(whereSqls, "op_resource_type=?") + whereArgs = append(whereArgs, opType) + } + if opGroup != "" { + whereSqls = append(whereSqls, "op_resource_group=?") + whereArgs = append(whereArgs, opGroup) + } + if opKey != "" { + whereSqls = append(whereSqls, "op_resource_key=?") + whereArgs = append(whereArgs, opKey) + } + if method != "" { + whereSqls = append(whereSqls, "method=?") + whereArgs = append(whereArgs, method) + } + + tx := global.GLOB_DB + txCount := global.GLOB_DB.Model(new(History)) + if len(whereSqls) != 0 { + tx = tx.Where(strings.Join(whereSqls, " and "), whereArgs...) + txCount = txCount.Where(strings.Join(whereSqls, " and "), whereArgs...) + } + + limitStart := (pageNo - 1) * pageLen + err := tx.Offset(limitStart).Limit(pageLen).Order("created_at desc").Find(&list).Error + if err != nil { + return nil, 0, errcode.New(errcode.DBError, "list error:%v", err) + } + totalCount := int64(0) + err = txCount.Count(&totalCount).Error + if err != nil { + return nil, 0, errcode.New(errcode.DBError, "count error:%v", err) + } + return list, int(totalCount), nil +} diff --git a/admin/apps/user/server/ctl_user.go b/admin/apps/user/server/ctl_user.go index 9c2d16c..2913ca7 100644 --- a/admin/apps/user/server/ctl_user.go +++ b/admin/apps/user/server/ctl_user.go @@ -22,3 +22,12 @@ func (ctl *controller) GetUserInfo(ctx *context.WebContext, params *dto.NilReq, *rsp = *svcRsp return nil } + +func (ctl *controller) GetUserExecHistory(ctx *context.WebContext, params *dto.ListUserOpHistoryReq, rsp *dto.ListUserOpHistoryRsp) error { + rsp1, err := ctl.svc.ListUserExecHistory(params) + if err != nil { + return err + } + *rsp = *rsp1 + return nil +} diff --git a/admin/apps/user/server/route.go b/admin/apps/user/server/route.go index 0a97a3b..001566f 100644 --- a/admin/apps/user/server/route.go +++ b/admin/apps/user/server/route.go @@ -15,6 +15,7 @@ func (srv *Server) Route(engine *web.Engine) { userGroup := apiGroup.Group("/user", "用户操作组") userGroup.Post("/login", "登录", consts.WebPathPermit_Write, srv.ctl.Login) userGroup.Get("/info", "获取用户信息,里面包含用户权限信息,用于前端生成动态菜单", consts.WebPathPermit_Read, srv.ctl.GetUserInfo) + userGroup.Get("/history", "获取用户执行历史记录,按各种条件检索", consts.WebPathPermit_Read, srv.ctl.GetUserExecHistory) } { @@ -25,5 +26,4 @@ func (srv *Server) Route(engine *web.Engine) { userResourceGroup.Put("", "编辑", consts.WebPathPermit_Read, srv.ctl.CommonPut) userResourceGroup.Delete("", "删除", consts.WebPathPermit_Read, srv.ctl.CommonDelete) } - } diff --git a/admin/apps/user/server/server.go b/admin/apps/user/server/server.go index 7cdc2a1..3f5a56c 100644 --- a/admin/apps/user/server/server.go +++ b/admin/apps/user/server/server.go @@ -6,6 +6,7 @@ import ( "admin/internal/event" "admin/lib/xlog" "encoding/json" + "strconv" ) type Server struct { @@ -23,24 +24,41 @@ func New(svc *service.Service) *Server { } func (srv *Server) jobsSubscribe() { - event.GetMgrInstance().Subscribe("user", event.EventTopic_UserExecute, srv.subscriberHandlerUserExecute) + event.GetMgrInstance().Subscribe("user", event.EventTopic_UserGameExecute, srv.subscriberHandlerUserExecute) } func (srv *Server) subscriberHandlerUserExecute(msg *event.Msg) { po := new(model.History) - msgHistory := &event.EventPayload_UserExecute{} + msgHistory := &event.EventPayload_UserGameExecute{} err := json.Unmarshal(msg.Payload, msgHistory) if err != nil { xlog.Errorf("unmarshal msg(%+v) err:%v", string(msg.Payload), err) return } + userInfo, find, err := srv.ctl.svc.GetUserById(msgHistory.UserId) + if err != nil { + xlog.Errorf("find user %+v info error:%v", msgHistory, err) + } else if !find { + xlog.Errorf("not found user info:%+v", msgHistory) + } + po.UserId = msgHistory.UserId - po.UserName = msgHistory.UserName - po.ProjectId = msgHistory.ProjectId - po.Resource = msgHistory.Resource + po.UserName = strconv.Itoa(msgHistory.UserId) + if find { + po.UserName = userInfo.Po.UserName + } + po.OpResourceType = msgHistory.OpResourceType + po.OpResourceGroup = msgHistory.OpResourceGroup + po.OpResourceKey = msgHistory.OpResourceKey po.Method = msgHistory.Method - po.Data = string(msg.Payload) + b, _ := json.Marshal(&map[string]any{ + "project_id": msgHistory.ProjectId, + "project_name": msgHistory.ProjectName, + "src": msgHistory.SrcDataList, + "dst": msgHistory.DstDataList, + }) + po.DetailInfo = string(b) err = po.Create() if err != nil { diff --git a/admin/apps/user/service/service_user.go b/admin/apps/user/service/service_user.go index 00360dd..4734d26 100644 --- a/admin/apps/user/service/service_user.go +++ b/admin/apps/user/service/service_user.go @@ -10,6 +10,7 @@ import ( "admin/lib/tokenlib" "admin/lib/xlog" "context" + "time" ) func (svc *Service) CheckToken(token string, userId int) error { @@ -110,3 +111,39 @@ func (svc *Service) GetUserInfo(userId int) (*dto2.GetUserInfoRsp, error) { func (svc *Service) GetUserById(userId int) (*entity.User, bool, error) { return svc.resourceSvc.GetUserById(userId) } + +func (svc *Service) ListUserExecHistory(params *dto2.ListUserOpHistoryReq) (*dto2.ListUserOpHistoryRsp, error) { + list, totalCount, err := new(model.History).List(params.PageNo, params.PageLen, + params.UserId, params.OpResourceType, params.OpResourceGroup, params.OpResourceKey, params.Method) + if err != nil { + return nil, err + } + rsp := new(dto2.ListUserOpHistoryRsp) + rsp.List = make([]*dto2.UserOpHistoryInfo, 0) + userMap := make(map[int]*entity.User, 0) + for _, v := range list { + var userName = v.UserName + userInfo, find := userMap[v.UserId] + if !find { + userInfo, find, err := svc.resourceSvc.GetUserById(v.UserId) + if err == nil && find { + userName = userInfo.Po.UserName + userMap[v.UserId] = userInfo + } + } else { + userName = userInfo.Po.UserName + } + rsp.List = append(rsp.List, &dto2.UserOpHistoryInfo{ + UserId: v.UserId, + UserName: userName, + OpResourceType: v.OpResourceType, + OpResourceGroup: v.OpResourceGroup, + OpResourceKey: v.OpResourceKey, + Method: v.Method, + CreatedAt: v.CreatedAt.Format(time.DateTime), + DetailInfo: v.DetailInfo, + }) + } + rsp.TotalCount = totalCount + return rsp, nil +} diff --git a/admin/internal/consts/consts.go b/admin/internal/consts/consts.go index d0e95dd..7689ce9 100644 --- a/admin/internal/consts/consts.go +++ b/admin/internal/consts/consts.go @@ -67,3 +67,7 @@ const ( BtnKeyRow_Server_Down = "server:down" BtnKeyRow_Server_Up = "server:up" ) + +const ( + CDKeyBatchMaxKeyNum = 1000000 // 奖励码一批最大数量,不然运营想补加码,算法又要一开始定好数量 +) diff --git a/admin/internal/event/topic.go b/admin/internal/event/topic.go index 6f7fb64..cfa1463 100644 --- a/admin/internal/event/topic.go +++ b/admin/internal/event/topic.go @@ -3,19 +3,20 @@ package event import "time" const ( - EventTopic_UserExecute = "user.execute" + EventTopic_UserGameExecute = "user.game.execute" EventTopic_DelayInvokeCreateHook = "resource.create.delay" ) -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"` - Any any `json:"any"` +type EventPayload_UserGameExecute struct { + UserId int + ProjectId int + ProjectName string + OpResourceType string + OpResourceGroup string + OpResourceKey string + Method string + SrcDataList []any + DstDataList []any } type EventPayload_DelayInvokeCreateHook struct { diff --git a/admin/internal/model/dto/common.go b/admin/internal/model/dto/common.go index d851438..7b19144 100644 --- a/admin/internal/model/dto/common.go +++ b/admin/internal/model/dto/common.go @@ -127,3 +127,14 @@ type TokenInfo struct { Token string `json:"token"` ExpireAt int64 `json:"expire_at"` } + +type UserOpHistoryInfo struct { + UserId int `json:"userId"` + UserName string `json:"userName"` + OpResourceType string `json:"opResourceType"` + OpResourceGroup string `json:"opResourceGroup"` + OpResourceKey string `json:"opResourceKey"` + Method string `json:"method"` + CreatedAt string `json:"createdAt"` + DetailInfo string `json:"detailInfo"` +} diff --git a/admin/internal/model/dto/msg_project.go b/admin/internal/model/dto/msg_project.go index 9607c49..768eb81 100644 --- a/admin/internal/model/dto/msg_project.go +++ b/admin/internal/model/dto/msg_project.go @@ -51,6 +51,7 @@ type CommonRowsSelectionReq struct { type CommonRowsSelectionRsp struct { Msg string `json:"msg"` NeedRefresh bool `json:"need_refresh"` + ShortDesc string `json:"short_desc"` } type CommandListReq struct { diff --git a/admin/internal/model/dto/msg_user.go b/admin/internal/model/dto/msg_user.go index 94482e5..4b693ea 100644 --- a/admin/internal/model/dto/msg_user.go +++ b/admin/internal/model/dto/msg_user.go @@ -20,3 +20,18 @@ type LoginRsp struct { } type GetUserInfoRsp = LoginRsp + +type ListUserOpHistoryReq struct { + PageNo int `json:"pageNo"` + PageLen int `json:"pageLen"` + UserId int `json:"userId"` + OpResourceType string `json:"opResourceType"` + OpResourceGroup string `json:"opResourceGroup"` + OpResourceKey string `json:"opResourceKey"` + Method string `json:"method"` +} + +type ListUserOpHistoryRsp struct { + List []*UserOpHistoryInfo `json:"list"` + TotalCount int `json:"totalCount"` +} diff --git a/ui/src/api/sys.js b/ui/src/api/sys.js index 7fa7284..f58ec98 100644 --- a/ui/src/api/sys.js +++ b/ui/src/api/sys.js @@ -21,4 +21,22 @@ export function generateRoutes() { url: "/routes", method: "get" }) +} + +export function getUserExecHistory(pageNo, pageLen, userId, opResourceType, opResourceGroup, opResourceKey, method) { + const p = { + pageNo, + pageLen, + userId, + opResourceType, + opResourceGroup, + opResourceKey, + method + } + console.log("params:", p) + return request({ + url: "/user/history", + method: "get", + params: p + }) } \ No newline at end of file diff --git a/ui/src/components/restful/tableUser.vue b/ui/src/components/restful/tableUser.vue index 6b470e9..4fe4f78 100644 --- a/ui/src/components/restful/tableUser.vue +++ b/ui/src/components/restful/tableUser.vue @@ -10,6 +10,17 @@ import {getProjects} from "@/stores/user.js"; const cachedResource = LocalCache.getCache("resource"); +const props = defineProps({ + rowClickDialogBtns: Array, +}) + +let rowClickDialogBtns = [] +if (props.rowClickDialogBtns) { + rowClickDialogBtns = props.rowClickDialogBtns +} +const rowClickBtnVisibleList = reactive(rowClickDialogBtns.map(() => false)) +const rowClickBtnSelectRow = ref(null) + const listRsp = ref({fields_desc: [], rows: []}) const listDataOK = ref(false) const resource_raw_node = cachedResource; @@ -318,6 +329,12 @@ const handlePaginationCurChange = (val) => { listData() } +const tableSelectRow3 = (i, row) => { + rowClickBtnSelectRow.value = row + rowClickBtnVisibleList[i] = true + console.log("点击按钮:", rowClickBtnSelectRow) +} + @@ -582,6 +624,16 @@ const handlePaginationCurChange = (val) => { + + diff --git a/ui/src/components/user/history.vue b/ui/src/components/user/history.vue new file mode 100644 index 0000000..79276c0 --- /dev/null +++ b/ui/src/components/user/history.vue @@ -0,0 +1,219 @@ + + + + + \ No newline at end of file diff --git a/ui/src/views/Home.vue b/ui/src/views/Home.vue index 303a52f..ba0f221 100644 --- a/ui/src/views/Home.vue +++ b/ui/src/views/Home.vue @@ -124,6 +124,9 @@ function logout() { + + + {{ nickName }} diff --git a/ui/src/views/user/history.vue b/ui/src/views/user/history.vue index 0afe174..2899ff4 100644 --- a/ui/src/views/user/history.vue +++ b/ui/src/views/user/history.vue @@ -1,9 +1,11 @@