Quellcode durchsuchen

update 新增后台操作记录接口

Alvin vor 8 Monaten
Ursprung
Commit
dc3aad56ab

+ 6 - 1
game/game_cluster/nodes/webadmin/common/redisKey.go

@@ -1,9 +1,14 @@
 package common
 
 const (
-	AdminTokenPrefix = "admin::token::"
+	AdminTokenPrefix    = "admin::token::"
+	AdminUserNamePrefix = "admin:username:"
 )
 
 func GetTokenKey(key string) string {
 	return AdminTokenPrefix + key
 }
+
+func GetUserNameKey(key string) string {
+	return AdminUserNamePrefix + key
+}

+ 42 - 0
game/game_cluster/nodes/webadmin/controller/synthesis.go

@@ -124,3 +124,45 @@ func (s *Synthesis) FindUserLevel(ctx *gin.Context) {
 
 	common.PackOkResult(ctx, code.OK, resp)
 }
+
+// 综合统计
+func (s *Synthesis) Overview(ctx *gin.Context) {
+	// TODO Overview
+}
+
+// 活动统计
+func (s *Synthesis) Activity(ctx *gin.Context) {
+	// TODO Activity
+}
+
+// 转盘统计
+func (s *Synthesis) Turntable(ctx *gin.Context) {
+	// TODO Turntable
+}
+
+// 资产统计
+func (s *Synthesis) Assets(ctx *gin.Context) {
+	// TODO Assets
+}
+
+// 邀请统计
+func (s *Synthesis) Invite(ctx *gin.Context) {
+	// TODO Invite
+}
+
+// 后台操作记录
+func (s *Synthesis) Records(ctx *gin.Context) {
+	var req entity.RecordListReq
+	if err := ctx.ShouldBindJSON(&req); err != nil {
+		common.PackOkResult(ctx, code.ParamError)
+		return
+	}
+
+	resp, err := s.sev.RecordList(req)
+	if err != nil {
+		common.PackOkResult(ctx, err.Code)
+		return
+	}
+
+	common.PackOkResult(ctx, code.OK, resp)
+}

+ 29 - 0
game/game_cluster/nodes/webadmin/entity/userLog.go

@@ -0,0 +1,29 @@
+package entity
+
+type RecordListReq struct {
+	ID        string `json:"id" bson:"_id"`              // ID
+	UserName  string `json:"user_name" bson:"user_name"` // 用户名
+	RoleId    string `json:"role_id" bson:"role_id"`     // 角色ID
+	StartTime int64  `json:"start_time"`                 // 开始时间
+	EndTime   int64  `json:"end_time"`                   // 结束时间
+	Page      int    `json:"page"`                       // 页码
+	Size      int    `json:"size"`                       // 每页数量
+}
+
+type RecordListResp struct {
+	Details []*RecordListDetail `json:"details"`
+	Total   int64               `json:"total"`
+}
+
+type RecordListDetail struct {
+	Id           string `json:"id" bson:"_id"`                      // 自增ID
+	Username     string `json:"user_name" bson:"user_name"`         // 用户名
+	RoleId       string `json:"role_id" bson:"role_id"`             // 角色ID
+	Path         string `json:"url" bson:"url"`                     // 请求路径
+	Method       string `json:"method" bson:"method"`               // 请求方法
+	StatusCode   int    `json:"status_code" bson:"status_code"`     // HTTP状态码
+	Dur          int64  `json:"dur" bson:"dur"`                     // 请求耗时(毫秒)
+	ClientIP     string `json:"client_ip" bson:"client_ip"`         // 客户端IP
+	ErrorMessage string `json:"error_message" bson:"error_message"` // 错误信息
+	CreatedAt    int64  `json:"created_at" bson:"created_at"`
+}

+ 18 - 0
game/game_cluster/nodes/webadmin/model/userLog.go

@@ -0,0 +1,18 @@
+package model
+
+type UserOperationLog struct {
+	Id           interface{} `json:"id" bson:"_id"`                      // 自增ID
+	Username     string      `json:"user_name" bson:"user_name"`         // 用户名
+	RoleId       string      `json:"role_id" bson:"role_id"`             // 角色ID
+	Path         string      `json:"url" bson:"url"`                     // 请求路径
+	Method       string      `json:"method" bson:"method"`               // 请求方法
+	StatusCode   int         `json:"status_code" bson:"status_code"`     // HTTP状态码
+	Dur          int64       `json:"dur" bson:"dur"`                     // 请求耗时(毫秒)
+	ClientIP     string      `json:"client_ip" bson:"client_ip"`         // 客户端IP
+	ErrorMessage string      `json:"error_message" bson:"error_message"` // 错误信息
+	CreatedAt    int64       `json:"created_at" bson:"created_at"`
+}
+
+func (m *UserOperationLog) TableName() string {
+	return "userOperationLog"
+}

+ 20 - 0
game/game_cluster/nodes/webadmin/router/middleware.go

@@ -7,12 +7,15 @@ import (
 
 	"github.com/gin-gonic/gin"
 	"github.com/go-redis/redis/v8"
+	mhayaTime "github.com/mhaya/extend/time"
 	cfacade "github.com/mhaya/facade"
 	"github.com/mhaya/game/game_cluster/internal/code"
 	"github.com/mhaya/game/game_cluster/internal/constant"
 	"github.com/mhaya/game/game_cluster/internal/mdb"
 	"github.com/mhaya/game/game_cluster/internal/mdb/models"
 	"github.com/mhaya/game/game_cluster/nodes/webadmin/common"
+	"github.com/mhaya/game/game_cluster/nodes/webadmin/model"
+	"github.com/mhaya/game/game_cluster/nodes/webadmin/service"
 	mhayaLogger "github.com/mhaya/logger"
 	"go.mongodb.org/mongo-driver/bson"
 	"go.mongodb.org/mongo-driver/mongo"
@@ -20,6 +23,9 @@ import (
 
 func Auth(settingObj cfacade.ProfileJSON) gin.HandlerFunc {
 	return func(c *gin.Context) {
+		// 请求开始时间
+		startTime := mhayaTime.Now().UnixMilli()
+
 		tokenString := c.GetHeader("Token")
 		if tokenString == "" {
 			common.PackUnauthorizedResult(c, code.UnauthorizedError, "token is empty")
@@ -77,6 +83,20 @@ func Auth(settingObj cfacade.ProfileJSON) gin.HandlerFunc {
 		}
 
 		c.Next()
+
+		userName, err := mdb.RDB.Get(context.Background(), common.GetUserNameKey(tokenString)).Result()
+		if err == nil {
+			service.NewSynthesis().InsertRecord(model.UserOperationLog{
+				Username:     userName,
+				RoleId:       roleId,
+				Path:         c.Request.URL.Path,
+				Method:       c.Request.Method,
+				StatusCode:   c.Writer.Status(),
+				Dur:          mhayaTime.Now().UnixMilli() - startTime,
+				ClientIP:     c.ClientIP(),
+				ErrorMessage: c.Errors.ByType(gin.ErrorTypePrivate).String(),
+			})
+		}
 	}
 }
 

+ 8 - 1
game/game_cluster/nodes/webadmin/service/admin.go

@@ -96,10 +96,17 @@ func (a *Admin) Login(ctx *gin.Context, username string, password string) (*enti
 			return nil, common.NewResult(code.InternalError)
 		}
 
+		// 保存token -> Username 到 redis 中 过期时间为1天
+		err = mdb.RDB.Set(ctx, common.GetUserNameKey(generateToken), user.Username, 24*time.Hour).Err()
+		if err != nil {
+			mhayaLogger.Warnf("Login Set generateToken Username error:%v", err)
+			return nil, common.NewResult(code.InternalError)
+		}
+
 		// 保存token -> RoleId 到 redis 中 过期时间为1天
 		err = mdb.RDB.Set(ctx, generateToken, user.RoleId, 24*time.Hour).Err()
 		if err != nil {
-			mhayaLogger.Warnf("Login Set generateToken error:%v", err)
+			mhayaLogger.Warnf("Login Set generateToken RoleId error:%v", err)
 			return nil, common.NewResult(code.InternalError)
 		}
 

+ 101 - 0
game/game_cluster/nodes/webadmin/service/synthesis.go

@@ -5,12 +5,14 @@ import (
 	"math"
 	"time"
 
+	mhayaTime "github.com/mhaya/extend/time"
 	"github.com/mhaya/game/game_cluster/internal/code"
 	"github.com/mhaya/game/game_cluster/internal/constant"
 	"github.com/mhaya/game/game_cluster/internal/mdb"
 	"github.com/mhaya/game/game_cluster/internal/mdb/models"
 	"github.com/mhaya/game/game_cluster/nodes/webadmin/common"
 	"github.com/mhaya/game/game_cluster/nodes/webadmin/entity"
+	"github.com/mhaya/game/game_cluster/nodes/webadmin/model"
 	mhayaLogger "github.com/mhaya/logger"
 	"github.com/spf13/cast"
 	"go.mongodb.org/mongo-driver/bson"
@@ -457,3 +459,102 @@ func (s *Synthesis) FindUserLevel() (*entity.UserLevelCountResp, *code.Result) {
 		Details: results,
 	}, nil
 }
+
+func (s *Synthesis) InsertRecord(param model.UserOperationLog) {
+	mhayaLogger.Warnf("InsertRecord param:%#v", param)
+
+	record := new(model.UserOperationLog)
+	collection := mdb.MDB.Collection(record.TableName())
+
+	insertData := bson.M{}
+	insertData["user_name"] = param.Username
+	insertData["role_id"] = param.RoleId
+	insertData["url"] = param.Path
+	insertData["method"] = param.Method
+	insertData["status_code"] = param.StatusCode
+	insertData["dur"] = param.Dur
+	insertData["client_ip"] = param.ClientIP
+	insertData["error_message"] = param.ErrorMessage
+	insertData["created_at"] = mhayaTime.Now().Unix()
+
+	_, err := collection.InsertOne(context.Background(), insertData)
+	if err != nil {
+		mhayaLogger.Warnf("InsertRecord InsertOne error:%v", err)
+		return
+	}
+}
+
+func (s *Synthesis) RecordList(req entity.RecordListReq) (*entity.RecordListResp, *code.Result) {
+	record := new(model.UserOperationLog)
+	collection := mdb.MDB.Collection(record.TableName())
+
+	// 构建过滤器
+	filter := bson.M{}
+
+	if req.UserName != "" {
+		filter["userName"] = req.UserName
+	}
+	if req.RoleId != "" {
+		filter["role_id"] = req.RoleId
+	}
+	if req.ID != "" {
+		id, err := primitive.ObjectIDFromHex(req.ID)
+		if err != nil {
+			mhayaLogger.Warnf("RecordList ObjectIDFromHex error:%v, req.ID:%s", err, req.ID)
+			return nil, common.NewResult(code.ParamError)
+		}
+
+		filter["id"] = id
+	}
+
+	if req.StartTime != 0 {
+		filter["createAt"] = bson.M{
+			"$gte": req.StartTime,
+			"$lte": req.EndTime,
+		}
+	}
+
+	// 设置分页选项
+	findOptions := options.Find()
+	findOptions.SetSkip(int64((req.Page - 1) * req.Size))
+	findOptions.SetLimit(int64(req.Size))
+	findOptions.SetSort(bson.D{{"created_at", -1}})
+
+	// 获取总数total
+	ctx, cancel := context.WithTimeout(context.Background(), 100*time.Second)
+	defer cancel()
+	count, err := collection.CountDocuments(ctx, filter)
+	if err != nil {
+		mhayaLogger.Warnf("RecordList CountDocuments error:%v", err)
+		return nil, common.NewResult(code.InternalError)
+	}
+
+	// 查询数据
+	var results []*entity.RecordListDetail
+	cursor, err := collection.Find(ctx, filter, findOptions)
+	if err != nil {
+		mhayaLogger.Warnf("RecordList Find error:%v", err)
+		return nil, common.NewResult(code.InternalError)
+	}
+	defer cursor.Close(ctx)
+
+	// 解析结果
+	for cursor.Next(ctx) {
+		var result entity.RecordListDetail
+		if err := cursor.Decode(&result); err != nil {
+			mhayaLogger.Warnf("RecordList Decode error:%v", err)
+			return nil, common.NewResult(code.InternalError)
+		}
+		results = append(results, &result)
+	}
+
+	if err := cursor.Err(); err != nil {
+		mhayaLogger.Warnf("RecordList cursor error:%v", err)
+		return nil, common.NewResult(code.InternalError)
+	}
+
+	return &entity.RecordListResp{
+		Details: results,
+		Total:   count,
+	}, nil
+}