Przeglądaj źródła

增加-数据结构

userxzz 9 miesięcy temu
rodzic
commit
16ecab4ef0

+ 52 - 2
game/game_cluster/internal/mdb/models/PlayerStat.go

@@ -41,51 +41,101 @@ type Preserve struct {
 
 var preserveConfig = []int64{2, 3, 7, 14, 30}
 
-// GetPlayerPreserve 获取用户留存
+// GetPlayerPreserve 根据开始和结束时间获取玩家的保留数据。
+// 该函数会检查时间参数是否合理,并限制查询时间范围不超过一周。
+// 参数:
+//
+//	startTime - 查询的开始时间戳。
+//	EndTime - 查询的结束时间戳。
+//
+// 返回值:
+//
+//	一个map,键是日期的时间戳,值是该日期玩家的保留数据列表。
+//	如果查询时间超过当前时间或查询范围超过一周,返回nil。
 func GetPlayerPreserve(startTime, EndTime int64) map[int64][]*Preserve {
+	// 检查开始和结束时间是否在将来,如果是,返回nil。
 	if startTime > mhayaTime.Now().Unix() || EndTime > mhayaTime.Now().Unix() {
 		return nil
 	}
+
+	// 将开始时间转换为Timestamp类型。
 	sTime := mhayaTime.CreateFromTimestamp(startTime).TOTimeStamp()
 
+	// 如果结束时间超过当前时间,则将结束时间设置为当前时间。
 	if EndTime > mhayaTime.Now().Unix() {
 		EndTime = mhayaTime.Now().Unix()
 	}
+
+	// 将结束时间转换为Timestamp类型。
 	eTime := mhayaTime.CreateFromTimestamp(EndTime).TOTimeStamp()
+
+	// 计算开始时间和结束时间的天数差。
 	day := mhayaTime.CreateFromTimestamp(sTime).DiffInDays(mhayaTime.CreateFromTimestamp(eTime))
+
+	// 如果天数差超过7天,返回nil。
 	if day > 7 {
 		return nil
 	}
+
+	// 初始化返回的map。
 	var ret = make(map[int64][]*Preserve, 0)
+
+	// 遍历每一天,获取每一天的玩家保留数据。
 	for i := 0; i < int(day); i++ {
+		// 计算当前日期的时间戳。
 		curTime := mhayaTime.CreateFromTimestamp(sTime).Add(time.Duration(i) * 24 * time.Hour).Unix()
+
+		// 获取并存储当前日期的玩家保留数据。
 		ret[curTime] = PlayerPreserve(curTime)
 	}
+
+	// 返回包含玩家保留数据的map。
 	return ret
 }
 
+// PlayerPreserve 计算玩家保留数据。
+//
+// 参数:
+//
+//	startTime - 统计周期的开始时间,用于确定从何时开始统计玩家保留数据。
+//
+// 返回值:
+//
+//	[]*Preserve - 一个指向Preserve结构体切片的指针,其中每个Preserve结构体包含玩家保留的相关信息。
 func PlayerPreserve(startTime int64) []*Preserve {
+	// 初始化保存保留数据的切片。
 	var preserve []*Preserve
+
+	// 获取新的玩家映射和当前周期内的新注册玩家数量。
 	cur, curNum := GetNewPlayerMap(startTime, DailyRecordNewRegistered)
 
+	// 将第一天的新玩家保留数据添加到结果集中。
 	preserve = append(preserve, &Preserve{ID: 1, Num: curNum, Ratio: "100%"})
 
+	// 遍历保留配置,计算每个周期的保留数据。
 	for _, v := range preserveConfig {
+		// 计算下一个统计周期的开始时间。
 		nextTime := mhayaTime.CreateFromTimestamp(startTime).Add(time.Duration(v-1) * 24 * time.Hour).Unix()
+		// 获取下一个周期内的老玩家映射和该周期内的老玩家数量。
 		next, nextNum := GetNewPlayerMap(nextTime, DailyRecordOldLogin)
+
+		// 如果下一个周期内没有老玩家登录,则将保留数据的数目记为0。
 		if nextNum == 0 {
 			preserve = append(preserve, &Preserve{ID: v, Num: 0, Ratio: ""})
 		} else {
+			// 计算在当前周期和下一个周期都出现过的玩家数量。
 			var num int
 			for key, _ := range next {
 				if _, ok := cur[key]; ok {
 					num++
 				}
 			}
+			// 计算并添加该周期的保留数据到结果集中。
 			preserve = append(preserve, &Preserve{ID: v, Num: num, Ratio: fmt.Sprintf("%.2f", float64(num)/float64(curNum)*100)})
 		}
-
 	}
+
+	// 返回计算得到的保留数据。
 	return preserve
 }
 

+ 1 - 0
game/game_cluster/nodes/web/sdk/sdk_pg.go

@@ -0,0 +1 @@
+package sdk

+ 6 - 4
game/game_cluster/nodes/webadmin/controller/admin.go

@@ -124,7 +124,8 @@ func (a *Admin) FindAll(ctx *gin.Context) {
 			"msg":  err.Error(),
 		})
 	}
-	resp, err := a.sev.FindAll(ctx, req.Page, req.Size, req.Username)
+
+	resp, total, err := a.sev.FindAll(ctx, req.Page, req.Size, req.Username)
 	if err != nil {
 		ctx.JSON(200, gin.H{
 			"code": 400,
@@ -133,9 +134,10 @@ func (a *Admin) FindAll(ctx *gin.Context) {
 		return
 	}
 	ctx.JSON(http.StatusOK, gin.H{
-		"code": 200,
-		"msg":  "success",
-		"data": resp,
+		"code":  200,
+		"msg":   "success",
+		"data":  resp,
+		"total": total,
 	})
 }
 

+ 2 - 2
game/game_cluster/nodes/webadmin/controller/role.go

@@ -313,10 +313,10 @@ func (r *Role) AddAccess(ctx *gin.Context) {
 // @Produce application/json
 // @Param data query entity.AccessDelReq true "删除权限路由"
 // @Success 200 {object} entity.Response
-// @Router /v1/admin/role/access/del [post]
+// @Router /v1/admin/role/access/del [Get]
 func (r *Role) DelAccess(ctx *gin.Context) {
 	req := new(entity.AccessDelReq)
-	if err := ctx.ShouldBindJSON(&req); err != nil {
+	if err := ctx.ShouldBindQuery(&req); err != nil {
 		ctx.JSON(200, gin.H{
 			"code": 400,
 			"msg":  err.Error(),

+ 39 - 10
game/game_cluster/nodes/webadmin/controller/synthesis.go

@@ -35,9 +35,10 @@ func (s *Synthesis) FindUserLogDaily(ctx *gin.Context) {
 		return
 	}
 	ctx.JSON(200, gin.H{
-		"code": 200,
-		"msg":  "success",
-		"data": resp,
+		"code":  200,
+		"msg":   "success",
+		"data":  resp,
+		"total": req.Total,
 	})
 }
 
@@ -60,9 +61,10 @@ func (s *Synthesis) FindUserRetention(ctx *gin.Context) {
 		return
 	} else {
 		ctx.JSON(200, gin.H{
-			"code": 200,
-			"msg":  "success",
-			"data": resp,
+			"code":  200,
+			"msg":   "success",
+			"data":  resp,
+			"total": req.Total,
 		})
 	}
 
@@ -96,7 +98,8 @@ func (s *Synthesis) FindWithdrawal(ctx *gin.Context) {
 		})
 		return
 	}
-	resp, err := s.sev.FindWithdrawal(req)
+	var total int64
+	resp, total, err := s.sev.FindWithdrawal(req)
 	if err != nil {
 		ctx.JSON(200, gin.H{
 			"code": 400,
@@ -105,9 +108,10 @@ func (s *Synthesis) FindWithdrawal(ctx *gin.Context) {
 		return
 	} else {
 		ctx.JSON(200, gin.H{
-			"code": 200,
-			"msg":  "success",
-			"data": resp,
+			"code":  200,
+			"msg":   "success",
+			"data":  resp,
+			"total": total,
 		})
 	}
 }
@@ -137,6 +141,31 @@ func (s *Synthesis) WithdrawalStatus(ctx *gin.Context) {
 	}
 }
 
+// WithdrawalStatusBatch 修改提现状态批量
+func (s *Synthesis) WithdrawalStatusBatch(ctx *gin.Context) {
+	req := &entity.UserWithdrawalStatusBatch{}
+	if err := ctx.ShouldBindJSON(req); err != nil {
+		ctx.JSON(200, gin.H{
+			"code": 400,
+			"msg":  err.Error(),
+		})
+		return
+	}
+	err := s.sev.WithdrawalStatusBatch(req)
+	if err != nil {
+		ctx.JSON(200, gin.H{
+			"code": 400,
+			"msg":  err.Error(),
+		})
+		return
+	} else {
+		ctx.JSON(200, gin.H{
+			"code": 200,
+			"msg":  "success",
+		})
+	}
+}
+
 // FindUserLevel 查询用户等级
 func (s *Synthesis) FindUserLevel(ctx *gin.Context) {
 	resp, err := s.sev.FindUserLevel()

+ 10 - 6
game/game_cluster/nodes/webadmin/controller/whitelist.go

@@ -20,8 +20,8 @@ func NewWhitelist() *Whitelist {
 // @Accept json
 // @Produce json
 // @Param req body entity.WhitelistListReq true "请求参数"
-// @Success 200 {object} entity.WhitelistListResp "返回结果"
-// @Router /v1/admin/whitelist/getWhitelist [post]
+// @Success 200 {object} []models.Whitelist "返回结果"
+// @Router /v1/admin/whitelist/list [post]
 func (w *Whitelist) GetWhitelist(ctx *gin.Context) {
 	req := &entity.WhitelistListReq{}
 	if err := ctx.ShouldBindJSON(req); err != nil {
@@ -52,8 +52,8 @@ func (w *Whitelist) GetWhitelist(ctx *gin.Context) {
 // @Accept json
 // @Produce json
 // @Param req body entity.WhitelistAddReq true "请求参数"
-// @Success 200 {object} entity.WhitelistAddResp "返回结果"
-// @Router /v1/admin/whitelist/addWhitelist [post]
+// @Success 200 {object} entity.Response "返回结果"
+// @Router /v1/admin/whitelist/add [post]
 func (w *Whitelist) AddWhitelist(ctx *gin.Context) {
 	req := &entity.WhitelistAddReq{}
 	if err := ctx.ShouldBindJSON(req); err != nil {
@@ -63,7 +63,7 @@ func (w *Whitelist) AddWhitelist(ctx *gin.Context) {
 		})
 		return
 	}
-	err := new(service.Whitelist).Add(req.IP)
+	err := new(service.Whitelist).Add(req.IP, req.Desc)
 	if err != nil {
 		ctx.JSON(200, gin.H{
 			"code": 400,
@@ -71,6 +71,9 @@ func (w *Whitelist) AddWhitelist(ctx *gin.Context) {
 		})
 		return
 	}
+	ctx.JSON(200, gin.H{
+		"code": 200,
+	})
 }
 
 // RemoveWhitelist 删除白名单
@@ -80,7 +83,8 @@ func (w *Whitelist) AddWhitelist(ctx *gin.Context) {
 // @Accept json
 // @Produce json
 // @Param req body entity.WhitelistRemoveReq true "请求参数"
-// @Success 200 {object} entity.WhitelistRemoveResp "返回结果"
+// @Success 200 {object} entity.Response "返回结果"
+// @Router /v1/admin/whitelist/remove [post]
 func (w *Whitelist) RemoveWhitelist(ctx *gin.Context) {
 	req := &entity.WhitelistRemoveReq{}
 	if err := ctx.ShouldBindJSON(req); err != nil {

+ 1 - 0
game/game_cluster/nodes/webadmin/entity/admin.go

@@ -33,6 +33,7 @@ type AdminFindAllReq struct {
 	Page     int    `json:"page"`
 	Size     int    `json:"size"`
 	Username string `json:"username"`
+	Total    int64  `json:"total"`
 }
 
 type AdminUpdateStatusReq struct {

+ 1 - 0
game/game_cluster/nodes/webadmin/entity/user_log_daily.go

@@ -24,4 +24,5 @@ type UserLogDailyReq struct {
 	Channel   string `json:"channel"`
 	Page      int    `json:"page"`
 	Size      int    `json:"size"`
+	Total     int64  `json:"total"`
 }

+ 1 - 0
game/game_cluster/nodes/webadmin/entity/user_reg_count.go

@@ -12,6 +12,7 @@ type UserRetentionReq struct {
 	EndTime   int64 `json:"end_time"`   // 结束时间
 	Page      int   `json:"page"`       // 页码
 	Size      int   `json:"size"`       // 每页数量
+	Total     int64 `json:"total"`
 }
 
 // UserRetentionData 用于存储用户的留存数据

+ 13 - 3
game/game_cluster/nodes/webadmin/entity/user_withdrawal.go

@@ -2,9 +2,12 @@ package entity
 
 // UserWithdrawalResp \game\game_cluster\nodes\webadmin\entity\user_withdrawal.go
 type UserWithdrawalResp struct {
+	Id          string      `json:"id" bson:"_id"`                    // Id
 	UserName    string      `json:"user_name" bson:"userName"`        // 用户ID
 	NickName    string      `json:"nick_name" bson:"nickName"`        // 昵称
-	Status      interface{} `json:"status" bson:"status"`             // 0:未审核 1:审核通过 2:审核失败
+	Status      int         `json:"status" bson:"status"`             // 0:未审核 1:审核通过 2:审核失败
+	Reason      string      `json:"reason" bson:"reason"`             // 提现原因
+	Withdrawal  int         `json:"withdrawal" bson:"withdrawal"`     // 提现 1:提现成功 2:提现中 3:提现失败 4:拒绝提现
 	Amount      int         `json:"amount" bson:"amount"`             // 提现金额
 	AfterAmount int         `json:"after_amount" bson:"after_amount"` // 提现后金额
 	Type        interface{} `json:"type" bson:"type"`                 // 货币内型
@@ -23,6 +26,13 @@ type UserWithdrawalReq struct {
 }
 
 type UserWithdrawalStatus struct {
-	UserName string `json:"user_name" bson:"user_name"` // 用户ID
-	Status   int32  `json:"status" bson:"status"`       // 0:未审核 1:审核通过 2:审核失败
+	UserName   string `json:"user_name" bson:"user_name" binding:"required"` // 用户ID
+	Status     int    `json:"status" bson:"status" `                         // 0:未审核 1:审核通过 2:审核失败
+	Withdrawal int    `json:"withdrawal" bson:"withdrawal"`                  // 提现 1:提现成功 2:提现中 3:提现失败 4:拒绝提现
+}
+
+type UserWithdrawalStatusBatch struct {
+	ID         []string `json:"id" bson:"id" binding:"required"` // 用户ID
+	Status     int      `json:"status" bson:"status"`            // 0:未审核 1:审核通过 2:审核失败
+	Withdrawal int      `json:"withdrawal" bson:"withdrawal"`    // 提现 1:提现成功 2:提现中 3:提现失败 4:拒绝提现
 }

+ 1 - 0
game/game_cluster/nodes/webadmin/router/router.go

@@ -42,6 +42,7 @@ func (c *Controller) InitApiRouter(u *gin.RouterGroup) {
 	u.POST("/user/country", controller.NewSynthesis().FindUserCountryCount)
 	u.POST("/user/withdrawal", controller.NewSynthesis().FindWithdrawal)
 	u.POST("/user/withdrawal/status", controller.NewSynthesis().WithdrawalStatus)
+	u.POST("/user/withdrawal/status_batch", controller.NewSynthesis().WithdrawalStatusBatch)
 	u.POST("/user/level", controller.NewSynthesis().FindUserLevel)
 	u.POST("/user/changePassword", controller.NewAdmin().ChangePassword)
 	u.POST("/user/add", controller.NewAdmin().Add)

+ 10 - 5
game/game_cluster/nodes/webadmin/service/admin.go

@@ -251,7 +251,7 @@ func (a *Admin) UpdateStatus(ctx context.Context, username string, status int) e
 }
 
 // FindAll 查找所有管理员信息
-func (a *Admin) FindAll(ctx context.Context, page int, pageSize int, username string) ([]*model.Admin, error) {
+func (a *Admin) FindAll(ctx context.Context, page int, pageSize int, username string) ([]*model.Admin, int64, error) {
 	// 日志记录
 	log.Printf("Finding admins with page %d and page size %d, username: %s", page, pageSize, maskUsername(username))
 
@@ -268,6 +268,11 @@ func (a *Admin) FindAll(ctx context.Context, page int, pageSize int, username st
 	if username != "" {
 		filter["username"] = bson.M{"$regex": escapeRegex(username), "$options": "i"}
 	}
+	// 查询总数
+	count, err := mdb.MDB.Collection("admin").CountDocuments(ctx, filter)
+	if err != nil {
+		return nil, 0, err
+	}
 
 	// 设置分页选项
 	skip := (page - 1) * pageSize
@@ -277,7 +282,7 @@ func (a *Admin) FindAll(ctx context.Context, page int, pageSize int, username st
 	// 执行查询
 	cursor, err := mdb.MDB.Collection("admin").Find(ctx, filter, findOptions)
 	if err != nil {
-		return nil, err
+		return nil, 0, err
 	}
 	defer func() {
 		if closeErr := cursor.Close(ctx); closeErr != nil {
@@ -291,16 +296,16 @@ func (a *Admin) FindAll(ctx context.Context, page int, pageSize int, username st
 		var admin model.Admin
 		err := cursor.Decode(&admin)
 		if err != nil {
-			return nil, err
+			return nil, 0, err
 		}
 		admins = append(admins, &admin)
 	}
 
 	if err := cursor.Err(); err != nil {
-		return nil, err
+		return nil, 0, err
 	}
 
-	return admins, nil
+	return admins, count, nil
 }
 
 // GetServerStatus 获取服务器状态

+ 25 - 5
game/game_cluster/nodes/webadmin/service/role.go

@@ -257,6 +257,7 @@ func (r *Role) GetRoleAccessList(ctx context.Context, req entity.RoleAccessListR
 			log.Printf("Failed to decode document: %v", err)
 			return nil, err
 		}
+
 		accessIDS = append(accessIDS, roleAccess.AccessID...)
 	}
 
@@ -264,11 +265,15 @@ func (r *Role) GetRoleAccessList(ctx context.Context, req entity.RoleAccessListR
 	if len(accessIDS) == 0 {
 		return nil, nil
 	}
-
+	var objIDS []primitive.ObjectID
+	for _, v := range accessIDS {
+		objID, _ := primitive.ObjectIDFromHex(v)
+		objIDS = append(objIDS, objID)
+	}
 	// 根据accessIDS查询权限列表 并且按照下级关系组合
 	access := models.Access{}
 	collection = mdb.MDB.Collection(access.TableName())
-	accessFilter := bson.M{"id": bson.M{"$in": accessIDS}}
+	accessFilter := bson.M{"_id": bson.M{"$in": objIDS}}
 	cursor, err = collection.Find(ctx, accessFilter)
 	defer cursor.Close(ctx)
 	if err != nil {
@@ -347,7 +352,9 @@ func (r *Role) DelAccess(ctx context.Context, req entity.AccessDelReq) error {
 	if err := collection.FindOne(ctx, filter).Err(); err == nil {
 		return fmt.Errorf("权限已被角色使用,无法删除")
 	}
-	_, err := collection.DeleteOne(ctx, bson.M{"id": req.Id})
+	objID := primitive.ObjectID{}
+	objID, _ = primitive.ObjectIDFromHex(req.Id)
+	_, err := collection.DeleteOne(ctx, bson.M{"_id": objID})
 	return err
 }
 
@@ -688,7 +695,11 @@ func validateConcurrently(ctx context.Context, req entity.RoleAccessUpdateReq) e
 func validateRoleExistence(ctx context.Context, req entity.RoleAccessUpdateReq) error {
 	roles := models.Roles{}
 	collection := mdb.MDB.Collection(roles.TableName())
-	if err := collection.FindOne(ctx, bson.M{"id": req.RoleId}).Err(); err != nil {
+	objID, err := primitive.ObjectIDFromHex(req.RoleId)
+	if err != nil {
+		return fmt.Errorf("解析角色ID失败: %v", err)
+	}
+	if err := collection.FindOne(ctx, bson.M{"_id": objID}).Err(); err != nil {
 		if errors.Is(err, mongo.ErrNoDocuments) {
 			return fmt.Errorf("角色不存在")
 		}
@@ -701,7 +712,16 @@ func validateRoleExistence(ctx context.Context, req entity.RoleAccessUpdateReq)
 func validateAccessExistence(ctx context.Context, req entity.RoleAccessUpdateReq) error {
 	access := models.Access{}
 	collection := mdb.MDB.Collection(access.TableName())
-	filter := bson.M{"id": bson.M{"$in": req.AccessId}} // 数组查询
+	objIDS := make([]primitive.ObjectID, len(req.AccessId))
+	for i, id := range req.AccessId {
+		objID, err := primitive.ObjectIDFromHex(id)
+		if err != nil {
+			return fmt.Errorf("解析权限ID失败: %v", err)
+		}
+		objIDS[i] = objID
+	}
+
+	filter := bson.M{"_id": bson.M{"$in": objIDS}} // 数组查询
 	if err := collection.FindOne(ctx, filter).Err(); err != nil {
 		if errors.Is(err, mongo.ErrNoDocuments) {
 			return fmt.Errorf("权限不存在")

+ 46 - 8
game/game_cluster/nodes/webadmin/service/synthesis.go

@@ -2,6 +2,7 @@ package service
 
 import (
 	"context"
+	"errors"
 	"math"
 	"time"
 
@@ -11,6 +12,7 @@ import (
 	"github.com/mhaya/game/game_cluster/nodes/webadmin/entity"
 	"github.com/spf13/cast"
 	"go.mongodb.org/mongo-driver/bson"
+	"go.mongodb.org/mongo-driver/bson/primitive"
 	"go.mongodb.org/mongo-driver/mongo"
 	"go.mongodb.org/mongo-driver/mongo/options"
 )
@@ -53,6 +55,13 @@ func (s *Synthesis) FindMDBUserLogDaily(req *entity.UserLogDailyReq) ([]entity.U
 
 	// 分页参数
 	skip := (req.Page - 1) * req.Size
+	req.Total = 0
+	// 计算总数
+	count, err := collection.CountDocuments(ctx, filter)
+	if err != nil {
+		return nil, err
+	}
+	req.Total = count
 
 	// 执行查询
 	opts := options.Find()
@@ -110,7 +119,7 @@ func (s *Synthesis) FindMDBUserLogDaily(req *entity.UserLogDailyReq) ([]entity.U
 }
 
 // FindWithdrawal 根据请求查询提现记录
-func (s *Synthesis) FindWithdrawal(req *entity.UserWithdrawalReq) ([]*entity.UserWithdrawalResp, error) {
+func (s *Synthesis) FindWithdrawal(req *entity.UserWithdrawalReq) ([]*entity.UserWithdrawalResp, int64, error) {
 	ctx, cancel := context.WithTimeout(context.Background(), 100*time.Second)
 	defer cancel()
 	collection := mdb.MDB.Collection(constant.CNameCashOutRecord)
@@ -136,28 +145,31 @@ func (s *Synthesis) FindWithdrawal(req *entity.UserWithdrawalReq) ([]*entity.Use
 	findOptions.SetSkip(int64((req.Page - 1) * req.Size))
 	findOptions.SetLimit(int64(req.Size))
 
+	// 获取总数total
+	count, err := collection.CountDocuments(ctx, filter)
+	if err != nil {
+		return nil, 0, err
+	}
+
 	// 查询数据
 	var results []*entity.UserWithdrawalResp
 	cursor, err := collection.Find(ctx, filter, findOptions)
 	if err != nil {
-		return nil, err
+		return nil, 0, err
 	}
 	defer cursor.Close(ctx)
-
 	// 解析结果
 	for cursor.Next(ctx) {
 		var result entity.UserWithdrawalResp
 		if err := cursor.Decode(&result); err != nil {
-			return nil, err
+			return nil, 0, err
 		}
 		results = append(results, &result)
 	}
-
 	if err := cursor.Err(); err != nil {
-		return nil, err
+		return nil, 0, err
 	}
-
-	return results, nil
+	return results, count, nil
 }
 
 // WithdrawalStatus 更新提现状态
@@ -180,6 +192,32 @@ func (s *Synthesis) WithdrawalStatus(req *entity.UserWithdrawalStatus) error {
 	return nil
 }
 
+// WithdrawalStatusBatch 更新提现状态
+func (s *Synthesis) WithdrawalStatusBatch(req *entity.UserWithdrawalStatusBatch) error {
+	collection := mdb.MDB.Collection(constant.CNameCashOutRecord)
+	if len(req.ID) == 0 {
+		return errors.New("id 不能为空")
+	}
+	for _, id := range req.ID {
+		objID := primitive.ObjectID{}
+		objID, _ = primitive.ObjectIDFromHex(id)
+		updateCondition := bson.M{"_id": objID}
+		updateContent := bson.M{}
+		if req.Withdrawal != 0 {
+			updateContent = bson.M{"$set": bson.M{"withdrawal": req.Withdrawal}}
+		}
+		if req.Status > 0 {
+			updateContent = bson.M{"$set": bson.M{"status": req.Status}}
+		}
+		updateOptions := options.Update().SetUpsert(true)
+		_, err := collection.UpdateOne(context.TODO(), updateCondition, updateContent, updateOptions)
+		if err != nil {
+			continue
+		}
+	}
+	return nil
+}
+
 // FindUserCountryCount 查询用户国家分布
 //
 // 返回值为 UserCountryResp 的切片和错误。

+ 9 - 5
game/game_cluster/nodes/webadmin/service/whitelist.go

@@ -4,14 +4,15 @@ import (
 	"context"
 	"errors"
 	"fmt"
+	"log"
+	"time"
+
 	"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/entity"
 	"go.mongodb.org/mongo-driver/bson"
 	"go.mongodb.org/mongo-driver/mongo"
 	"go.mongodb.org/mongo-driver/mongo/options"
-	"log"
-	"time"
 )
 
 type Whitelist struct {
@@ -22,7 +23,7 @@ func NewWhitelist() *Whitelist {
 }
 
 // Add 添加IP白名单
-func (w *Whitelist) Add(ip string) error {
+func (w *Whitelist) Add(ip, de string) error {
 	whitelistModel := models.Whitelist{}
 	collection := mdb.MDB.Collection(whitelistModel.TableName())
 	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
@@ -32,8 +33,11 @@ func (w *Whitelist) Add(ip string) error {
 	if err == nil {
 		return fmt.Errorf("IP %s already exists in the whitelist", ip)
 	}
-	_, err = collection.InsertOne(ctx, models.Whitelist{
-		IP: ip,
+	_, err = collection.InsertOne(ctx, bson.M{
+		"ip":         ip,
+		"created_at": time.Now(),
+		"updated_at": time.Now(),
+		"desc":       de,
 	})
 	if err != nil {
 		log.Printf("Error inserting IP %s into whitelist: %v", ip, err)