8 Commits 76b1d495ae ... 5fcdde4b72

Author SHA1 Message Date
  Alvin 5fcdde4b72 update 完善玩家详情 10 months ago
  Alvin 0cc9590144 update 玩家详情增加字段 10 months ago
  Alvin ccea7518b1 update 完善获取转盘中奖记录 10 months ago
  Alvin 18816208c4 update 完善获取转盘中奖记录 10 months ago
  Alvin dcb9d127af update 修改玩家列表等级过滤 10 months ago
  Alvin e71ac66af5 update 修改开始时间、结束时间默认值 10 months ago
  Alvin 821d5eb7d7 update 新增获取玩家中奖记录(默认查询最近三天)接口 10 months ago
  Alvin 587a64e3a0 update 新增玩家列表接口、玩家详情接口 10 months ago

+ 64 - 0
game/game_cluster/internal/mdb/models/reward.go

@@ -1,7 +1,10 @@
 package models
 
 import (
+	cutils "github.com/mhaya/extend/utils"
+	"github.com/mhaya/game/game_cluster/internal/constant"
 	"github.com/mhaya/game/game_cluster/internal/data"
+	"go.mongodb.org/mongo-driver/bson"
 )
 
 const (
@@ -34,3 +37,64 @@ type PlayerReward map[int]*PlayerRewardBase
 func NewPlayerReward() map[int]*PlayerRewardBase {
 	return make(map[int]*PlayerRewardBase)
 }
+
+type ToPlayerRewardBase struct {
+	UserName   string          `json:"userName" bson:"userName"`
+	AddReward  []*ToItemReward `json:"AddReward" bson:"addReward"`
+	Desc       interface{}     `json:"desc" bson:"desc"`
+	CreateTime int64           `json:"createTime" bson:"createTime"`
+}
+
+type ToItemReward struct {
+	ItemID   int     // itemID:道具ID
+	Amount   float64 // amount:数量
+	ItemName string  // itemName:道具名称
+}
+
+type ToDesc struct {
+	ID    int `json:"id" bson:"id"`
+	CurID int `json:"cur_id" bson:"curid"`
+}
+
+func (uw *PlayerRewardBase) To() *ToPlayerRewardBase {
+	return &ToPlayerRewardBase{
+		UserName: uw.UserName,
+		AddReward: func() []*ToItemReward {
+			ret := make([]*ToItemReward, 0, 8)
+			for _, v := range uw.AddReward {
+				itemName := ""
+				cfg, exist := data.ItemConfig.Get(v.ItemID)
+				if exist {
+					itemName = cfg.ItemKey
+				}
+
+				ret = append(ret, &ToItemReward{
+					ItemID: v.ItemID,
+					Amount: func() float64 {
+						if itemName == "u" || itemName == "ton" {
+							return cutils.QuoInt64ByRatioToFloat64(int64(v.Amount), constant.MoneyRatio)
+						}
+
+						return float64(v.Amount)
+					}(),
+					ItemName: itemName,
+				})
+			}
+
+			return ret
+		}(),
+		Desc: func() *ToDesc {
+			if uw.Desc == nil {
+				return nil
+			}
+
+			drawMap := uw.Desc.(bson.D).Map()
+			return &ToDesc{
+				ID:    int(drawMap["id"].(int32)),
+				CurID: int(drawMap["curid"].(int32)),
+			}
+		}(),
+		// Desc:       uw.Desc,
+		CreateTime: uw.CreateTime,
+	}
+}

+ 91 - 0
game/game_cluster/nodes/webadmin/controller/player.go

@@ -0,0 +1,91 @@
+package controller
+
+import (
+	"github.com/gin-gonic/gin"
+	"github.com/mhaya/game/game_cluster/nodes/webadmin/entity"
+	"github.com/mhaya/game/game_cluster/nodes/webadmin/service"
+)
+
+type PlayerManage struct {
+	sev *service.PlayerManage
+}
+
+func NewPlayerManage() *PlayerManage {
+	return &PlayerManage{
+		sev: service.NewPlayerManage(),
+	}
+}
+
+func (w *PlayerManage) GetPlayerlist(ctx *gin.Context) {
+	req := entity.PlayerListReq{}
+	if err := ctx.ShouldBindJSON(&req); err != nil {
+		ctx.JSON(200, gin.H{
+			"code": 400,
+			"msg":  err.Error(),
+		})
+		return
+	}
+	resp, total, err := w.sev.List(ctx, req)
+	if err != nil {
+		ctx.JSON(200, gin.H{
+			"code": 400,
+			"msg":  err.Error(),
+		})
+		return
+	}
+	ctx.JSON(200, gin.H{
+		"code":  200,
+		"data":  resp,
+		"msg":   "success",
+		"total": total,
+	})
+}
+
+func (w *PlayerManage) GetPlayerInfo(ctx *gin.Context) {
+	req := entity.PlayerInfoReq{}
+	if err := ctx.ShouldBindJSON(&req); err != nil {
+		ctx.JSON(200, gin.H{
+			"code": 400,
+			"msg":  err.Error(),
+		})
+		return
+	}
+	resp, err := w.sev.PlayerInfo(ctx, req)
+	if err != nil {
+		ctx.JSON(200, gin.H{
+			"code": 400,
+			"msg":  err.Error(),
+		})
+		return
+	}
+	ctx.JSON(200, gin.H{
+		"code": 200,
+		"data": resp,
+		"msg":  "success",
+	})
+}
+
+func (w *PlayerManage) GetRewardList(ctx *gin.Context) {
+	req := entity.RewardListReq{}
+	if err := ctx.ShouldBindJSON(&req); err != nil {
+		ctx.JSON(200, gin.H{
+			"code": 400,
+			"msg":  err.Error(),
+		})
+		return
+	}
+	resp, total, err := w.sev.RewardList(ctx, req)
+	if err != nil {
+		ctx.JSON(200, gin.H{
+			"code": 400,
+			"msg":  err.Error(),
+		})
+		return
+	}
+	ctx.JSON(200, gin.H{
+		"code":  200,
+		"data":  resp,
+		"msg":   "success",
+		"total": total,
+	})
+}

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

@@ -1,5 +1,7 @@
 package entity
 
+import "github.com/mhaya/game/game_cluster/internal/mdb/models"
+
 // AdminResp \game\game_cluster\nodes\webadmin\entity\admin.go
 type AdminResp struct {
 	ToKen  string `json:"token"`
@@ -57,3 +59,104 @@ type AdminUpdateStatusReq struct {
 	Username string `json:"username"`
 	Status   int    `json:"status"`
 }
+
+type PlayerListReq struct {
+	Page        int    `json:"page" binding:"required"`
+	Size        int    `json:"size" binding:"required"`
+	UserName    string `json:"userName"`                    // 用户名
+	NickName    string `json:"nickName" bson:"nickName"`    // 昵称
+	OpenId      string `json:"openId" bson:"openId"`        // 对应tgid
+	Pid         string `json:"pid" bson:"pid"`              // 上级ID
+	XID         string `json:"xID" bson:"xID"`              // 绑定推特ID
+	TonWall     string `json:"tonWall" bson:"tonWall"`      // 绑定钱包地址
+	Email       string `json:"email" bson:"email"`          // 邮箱
+	LevelMin    int    `json:"levelMin" bson:"level"`       // 等级最小值
+	LevelMax    int    `json:"levelMax" bson:"level"`       // 等级最大值
+	Status      int    `json:"status" bson:"status"`        // 状态 1:有效 2:禁用
+	LoginIP     string `json:"loginIP" bson:"loginIP"`      // 登录IP
+	JoinTimeMin int64  `json:"joinTimeMin" bson:"joinTime"` // 注册时间最小值
+	JoinTimeMax int64  `json:"joinTimeMax" bson:"joinTime"` // 注册时间最大值
+}
+
+type PlayerListResp struct {
+	UserName      string `json:"userName" bson:"userName"`           // 用户名
+	OpenId        string `json:"openId" bson:"openId"`               // 对应tgid
+	UserNameMaybe string `json:"userNameMaybe" bson:"userNameMaybe"` // 昵称
+	NickName      string `json:"nickName" bson:"nickName"`           // 昵称
+	Pid           string `json:"pid" bson:"pid"`                     // 上级ID
+	XID           string `json:"xID" bson:"xID"`                     // 绑定推特ID
+	TonWall       string `json:"tonWall" bson:"tonWall"`             // 绑定钱包地址
+	Email         string `json:"email" bson:"email"`                 // 邮箱
+	Level         int    `json:"level" bson:"level"`                 // 等级
+	Status        int    `json:"status" bson:"status"`               // 状态  1:有效 2:禁用
+	LoginTime     int64  `json:"loginTime" bson:"loginTime"`         // 登陆时间
+	LoginIP       string `json:"loginIP" bson:"loginIP"`             // 登录IP
+	JoinIP        string `json:"joinIP" bson:"joinIP"`               // 注册IP
+	JoinTime      int64  `json:"joinTime" bson:"joinTime"`           // 注册时间
+}
+
+type PlayerInfoReq struct {
+	UserName string `json:"userName" binding:"required"` // 用户名
+}
+
+type PlayerInfoResp struct {
+	UserName       string               `json:"userName" bson:"userName"`             // 用户名
+	OpenId         string               `json:"openId" bson:"openId"`                 // 对应tgid
+	UserNameMaybe  string               `json:"userNameMaybe" bson:"userNameMaybe"`   // 昵称
+	NickName       string               `json:"nickName" bson:"nickName"`             // 昵称
+	Pid            string               `json:"pid" bson:"pid"`                       // 上级ID
+	XID            string               `json:"xID" bson:"xID"`                       // 绑定推特ID
+	TonWall        string               `json:"tonWall" bson:"tonWall"`               // 绑定钱包地址
+	Email          string               `json:"email" bson:"email"`                   // 邮箱
+	Level          int                  `json:"level" bson:"level"`                   // 等级
+	Status         int                  `json:"status" bson:"status"`                 // 状态  1:有效 2:禁用
+	LoginTime      int64                `json:"loginTime" bson:"loginTime"`           // 登陆时间
+	LoginIP        string               `json:"loginIP" bson:"loginIP"`               // 登录IP
+	JoinIP         string               `json:"joinIP" bson:"joinIP"`                 // 注册IP
+	JoinTime       int64                `json:"joinTime" bson:"joinTime"`             // 注册时间
+	Avatar         string               `json:"avatar" bson:"avatar"`                 // 头像
+	IsRobot        int                  `json:"isRobot" bson:"isRobot"`               // 是否为机器人
+	IsLeader       int                  `json:"isLeader" bson:"isLeader"`             // 是否是社区长
+	IsVip          int                  `json:"isVip" bson:"isVip"`                   // 是否为VIP
+	Successions    int                  `json:"successions" bson:"successions"`       // 连续登陆天数
+	MaxSuccessions int                  `json:"maxSuccessions" bson:"maxSuccessions"` // 最大连续等级天数
+	PrevTime       int64                `json:"prevTime" bson:"prevTime"`             // 上次登陆时间
+	UpdateTime     int64                `json:"updateTime" bson:"updateTime"`         // 更新时间
+	IsDrawShare    int                  `json:"isDrawShare" bson:"isDrawShare"`       // 0未领取,1已领取
+	DrawShareTime  int64                `json:"drawShareTime" bson:"drawShareTime"`   // 领取时间
+	FirstReward    int                  `json:"firstReward" bson:"firstReward"`       // 是否已领取首次登陆奖励
+	Item           models.ItemBasePack  `json:"item" bson:"item"`                     // 道具
+	SinIn          models.SignIn        `json:"sinIn" bson:"sinIn"`                   // 签到
+	DailyTask      models.DailyTask     `json:"dailyTask" bson:"dailyTask"`           // 日常任务
+	AchieveTask    models.AchieveTask   `json:"achieveTask" bson:"achieveTask"`       // 成就任务
+	RankReward     models.RankReward    `json:"rankReward" bson:"rankReward"`         // 排行奖励
+	Invite         models.Invite        `json:"invite" bson:"invite"`                 // 邀请
+	InviteReward   *models.InviteReward `json:"inviteReward" bson:"inviteReward"`     // 邀请奖励
+	Roll           *models.Roll         `json:"roll" bson:"roll"`                     // 抽奖
+}
+
+type RewardListReq struct {
+	Page      int    `json:"page" binding:"required"`
+	Size      int    `json:"size" binding:"required"`
+	UserName  string `json:"userName"`   // 用户名
+	StartTime int64  `json:"start_time"` // 开始时间
+	EndTime   int64  `json:"end_time"`   // 结束时间
+}
+
+type RewardListResp struct {
+	UserName   string        `json:"userName" bson:"userName"` // 用户名
+	AddReward  []*ItemReward `json:"AddReward" bson:"addReward"`
+	Desc       *Desc         `json:"desc" bson:"desc"`
+	CreateTime int64         `json:"createTime" bson:"createTime"`
+}
+
+type Desc struct {
+	ID    int `json:"id"`     // 中奖位置
+	CurID int `json:"cur_id"` // 规则id
+}
+
+type ItemReward struct {
+	ItemID   int    // itemID:道具ID
+	Amount   int    // amount:数量
+	ItemName string // itemName:道具名称
+}

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

@@ -69,6 +69,9 @@ func (c *Controller) InitApiRouter(u *gin.RouterGroup) {
 	u.POST("/whitelist/add", controller.NewWhitelist().AddWhitelist)
 	u.POST("/whitelist/remove", controller.NewWhitelist().RemoveWhitelist)
 	u.POST("/whitelist/list", controller.NewWhitelist().GetWhitelist)
+	u.POST("/player/list", controller.NewPlayerManage().GetPlayerlist)
+	u.POST("/player/info", controller.NewPlayerManage().GetPlayerInfo)
+	u.POST("/player/rewardList", controller.NewPlayerManage().GetRewardList)
 }
 
 // func (c *Controller) InitMdb() {

+ 246 - 0
game/game_cluster/nodes/webadmin/service/playerMange.go

@@ -0,0 +1,246 @@
+package service
+
+import (
+	"context"
+	"log"
+	"time"
+
+	mhayaTime "github.com/mhaya/extend/time"
+	"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/entity"
+	"go.mongodb.org/mongo-driver/bson"
+	"go.mongodb.org/mongo-driver/mongo/options"
+)
+
+type PlayerManage struct {
+}
+
+func NewPlayerManage() *PlayerManage {
+	return &PlayerManage{}
+}
+
+// 获取玩家列表
+func (a *PlayerManage) List(ctx context.Context, req entity.PlayerListReq) ([]*entity.PlayerListResp, int64, error) {
+	page := req.Page
+	// 验证参数
+	if page <= 0 {
+		page = 1
+	}
+	pageSize := req.Size
+	if pageSize <= 0 {
+		pageSize = 10
+	}
+
+	// 构建查询条件
+	filter := bson.M{}
+	if req.UserName != "" {
+		filter["userName"] = bson.M{"$regex": escapeRegex(req.UserName), "$options": "i"}
+	}
+	if req.NickName != "" {
+		filter["nickName"] = bson.M{"$regex": escapeRegex(req.NickName), "$options": "i"}
+	}
+	if req.OpenId != "" {
+		filter["openId"] = req.OpenId
+	}
+	if req.Pid != "" {
+		filter["pid"] = req.Pid
+	}
+	if req.XID != "" {
+		filter["xID"] = req.XID
+	}
+	if req.TonWall != "" {
+		filter["tonWall"] = req.TonWall
+	}
+	if req.Email != "" {
+		filter["email"] = req.Email
+	}
+	if req.LevelMin > 0 && req.LevelMax == 0 {
+		filter["level"] = bson.M{
+			"$gte": req.LevelMin,
+			"$lte": 1000, // 等级最大值
+		}
+	}
+	if req.LevelMin >= 0 && req.LevelMax > 0 && req.LevelMin <= req.LevelMax {
+		filter["level"] = bson.M{
+			"$gte": req.LevelMin,
+			"$lte": req.LevelMax,
+		}
+	}
+	if req.Status > 0 {
+		filter["status"] = req.Status
+	}
+	if req.LoginIP != "" {
+		filter["loginIP"] = req.LoginIP
+	}
+	if req.JoinTimeMin > 0 && req.JoinTimeMax > 0 && req.JoinTimeMin <= req.JoinTimeMax {
+		filter["joinTime"] = bson.M{
+			"$gte": req.JoinTimeMin,
+			"$lte": req.JoinTimeMax,
+		}
+	}
+
+	// 设置分页选项
+	skip := (page - 1) * pageSize
+	limit := pageSize
+	findOptions := options.Find().SetSkip(int64(skip)).SetLimit(int64(limit))
+
+	// 执行查询
+	cursor, err := mdb.MDB.Collection(constant.CNamePlayer).Find(ctx, filter, findOptions)
+	if err != nil {
+		return nil, 0, err
+	}
+	defer func() {
+		if closeErr := cursor.Close(ctx); closeErr != nil {
+			log.Printf("Error closing cursor: %v", closeErr)
+		}
+	}()
+
+	// 解析结果
+	results := make([]*entity.PlayerListResp, 0)
+	for cursor.Next(ctx) {
+		var result entity.PlayerListResp
+		if err := cursor.Decode(&result); err != nil {
+			return nil, 0, err
+		}
+		results = append(results, &result)
+	}
+	if err := cursor.Err(); err != nil {
+		return nil, 0, err
+	}
+
+	count := 0
+	playerServerLoadStats, err := NewAdmin().GetServerStatus(ctx)
+	if err != nil {
+		return nil, 0, err
+	}
+
+	for _, v := range playerServerLoadStats {
+		count += int(v.TotalUser)
+	}
+
+	return results, int64(count), nil
+}
+
+// 获取玩家详情
+func (a *PlayerManage) PlayerInfo(ctx context.Context, req entity.PlayerInfoReq) (*entity.PlayerInfoResp, error) {
+	var player models.Player
+	err := mdb.MDB.Collection(constant.CNamePlayer).FindOne(context.Background(), bson.M{"userName": req.UserName}).Decode(&player)
+	if err != nil {
+		return nil, err
+	}
+
+	return &entity.PlayerInfoResp{
+		UserName:       player.UserName,
+		OpenId:         player.OpenId,
+		UserNameMaybe:  player.UserNameMaybe,
+		NickName:       player.NickName,
+		Pid:            player.Pid,
+		XID:            player.XID,
+		TonWall:        player.TonWall,
+		Email:          player.Email,
+		Level:          player.Level,
+		Status:         player.Status,
+		LoginTime:      player.LoginTime,
+		LoginIP:        player.LoginIP,
+		JoinIP:         player.JoinIP,
+		JoinTime:       player.JoinTime,
+		Avatar:         player.Avatar,
+		IsRobot:        player.IsRobot,
+		IsLeader:       player.IsLeader,
+		IsVip:          player.IsVip,
+		Successions:    player.Successions,
+		MaxSuccessions: player.MaxSuccessions,
+		PrevTime:       player.PrevTime,
+		UpdateTime:     player.UpdateTime,
+		IsDrawShare:    player.Share.IsDrawShare,
+		DrawShareTime:  player.Share.DrawShareTime,
+		FirstReward:    player.FirstReward,
+		Item:           player.Item,
+		SinIn:          player.SinIn,
+		DailyTask:      player.DailyTask,
+		AchieveTask:    player.AchieveTask,
+		RankReward:     player.RankReward,
+		Invite:         player.Invite,
+		InviteReward:   player.InviteReward,
+		Roll:           player.Roll,
+	}, nil
+}
+
+// 获取玩家中奖记录(默认查询最近三天)
+func (a *PlayerManage) RewardList(ctx context.Context, req entity.RewardListReq) ([]*models.ToPlayerRewardBase, int64, error) {
+	page := req.Page
+	// 验证参数
+	if page <= 0 {
+		page = 1
+	}
+	pageSize := req.Size
+	if pageSize <= 0 {
+		pageSize = 10
+	}
+
+	// 构建查询条件
+	filter := bson.M{}
+	if req.UserName != "" {
+		filter["userName"] = bson.M{"$regex": escapeRegex(req.UserName), "$options": "i"}
+	}
+	filter["source"] = models.SourceDraw
+
+	startTime := mhayaTime.Now().Add(-3 * 24 * time.Hour).Unix()
+	endTime := mhayaTime.Now().Unix()
+	if req.StartTime > 0 && req.StartTime >= startTime {
+		if req.StartTime <= req.EndTime || req.EndTime == 0 {
+			startTime = req.StartTime
+		}
+	}
+
+	if req.EndTime > 0 && req.EndTime <= endTime {
+		if req.StartTime <= req.EndTime {
+			endTime = req.EndTime
+		}
+	}
+
+	filter["createTime"] = bson.M{
+		"$gte": startTime,
+		"$lte": endTime,
+	}
+
+	// 设置分页选项
+	skip := (page - 1) * pageSize
+	limit := pageSize
+	findOptions := options.Find().SetSkip(int64(skip)).SetLimit(int64(limit))
+
+	collection := mdb.MDB.Collection(constant.CNamePlayerReward)
+	// 获取总数total
+	count, err := collection.CountDocuments(ctx, filter)
+	if err != nil {
+		return nil, 0, err
+	}
+
+	// 执行查询
+	cursor, err := collection.Find(ctx, filter, findOptions)
+	if err != nil {
+		return nil, 0, err
+	}
+	defer func() {
+		if closeErr := cursor.Close(ctx); closeErr != nil {
+			log.Printf("Error closing cursor: %v", closeErr)
+		}
+	}()
+
+	// 解析结果
+	results := make([]*models.ToPlayerRewardBase, 0)
+	for cursor.Next(ctx) {
+		var result models.PlayerRewardBase
+		if err := cursor.Decode(&result); err != nil {
+			return nil, 0, err
+		}
+		results = append(results, result.To())
+	}
+	if err := cursor.Err(); err != nil {
+		return nil, 0, err
+	}
+
+	return results, count, nil
+}