package service import ( "context" "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" "github.com/mhaya/game/game_cluster/nodes/webadmin/model" "github.com/spf13/cast" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" ) type Synthesis struct { db *mongo.Database } func NewSynthesis() *Synthesis { return &Synthesis{ db: mdb.MDB, } } func (s *Synthesis) FindMDBUserLogDaily(req *entity.UserLogDailyReq) ([]entity.UserLogDailyResp, error) { // 定义上下文 ctx, cancel := context.WithTimeout(context.Background(), 100*time.Second) defer cancel() // 指定集合 collection := mdb.MDB.Collection("playerDailyRecord") // 构建查询条件 - 如果查询值为空那就不添加查询条件 filter := bson.M{} if req.StartTime != 0 { filter["timestamp"] = bson.M{ "$gte": req.StartTime, "$lte": req.EndTime, } } if req.Platform != "" && req.Platform != "all" { filter["platform"] = req.Platform } if req.Channel != "" { filter["channel"] = req.Channel } // 分页参数 skip := (req.Page - 1) * req.Size // 执行查询 opts := options.Find() opts.SetSkip(int64(skip)) opts.SetLimit(int64(req.Size)) cursor, err := collection.Find(ctx, filter, opts) if err != nil { return nil, err } defer cursor.Close(ctx) // 解析查询结果 var results []entity.UserLogDailyResp for cursor.Next(ctx) { var result entity.UserLogDailyResp err := cursor.Decode(&result) if err != nil { return nil, err } results = append(results, result) } // 同一天的数据全部放到platform= ALl 且数据累加 // 如果没有platform=all 的那就新增一个 同一个时间段只能有一个 platform=all // 将同一天的数据累加到platform=all的记录中 allPlatformRecordMap := make(map[int64]*entity.UserLogDailyResp) for _, result := range results { allPlatformRecordMap[result.Timestamp] = &entity.UserLogDailyResp{ Timestamp: result.Timestamp, Platform: "all", } } for _, v := range results { if v.Timestamp == allPlatformRecordMap[v.Timestamp].Timestamp { allPlatformRecordMap[v.Timestamp].Registered += v.Registered allPlatformRecordMap[v.Timestamp].LoggedIn += v.LoggedIn allPlatformRecordMap[v.Timestamp].NewActive += v.NewActive allPlatformRecordMap[v.Timestamp].OldActive += v.OldActive allPlatformRecordMap[v.Timestamp].TotalPoints += v.TotalPoints allPlatformRecordMap[v.Timestamp].UProduced += v.UProduced allPlatformRecordMap[v.Timestamp].UCashout += v.UCashout allPlatformRecordMap[v.Timestamp].NewLogin += v.NewLogin allPlatformRecordMap[v.Timestamp].OldLogin += v.OldLogin } } // 替换原有结果 for _, record := range allPlatformRecordMap { results = append(results, *record) } return results, nil } // FindWithdrawal 根据请求查询提现记录 func (s *Synthesis) FindWithdrawal(req *entity.UserWithdrawalReq) ([]*entity.UserWithdrawalResp, error) { ctx, cancel := context.WithTimeout(context.Background(), 100*time.Second) defer cancel() collection := mdb.MDB.Collection("CashOutRecord") // 构建过滤器 filter := bson.M{} if req.UserName != "" { filter["userName"] = req.UserName } if req.NickName != "" { filter["nickName"] = req.NickName } if req.StartTime > 0 && req.EndTime > 0 { filter["createdAt"] = bson.M{"$gte": time.Unix(req.StartTime, 0), "$lte": time.Unix(req.EndTime, 0)} } else if req.StartTime > 0 { filter["createdAt"] = bson.M{"$gte": time.Unix(req.StartTime, 0)} } else if req.EndTime > 0 { filter["createdAt"] = bson.M{"$lte": time.Unix(req.EndTime, 0)} } // 设置分页选项 findOptions := options.Find() findOptions.SetSkip(int64((req.Page - 1) * req.Size)) findOptions.SetLimit(int64(req.Size)) // 查询数据 var results []*entity.UserWithdrawalResp cursor, err := collection.Find(ctx, filter, findOptions) if err != nil { return nil, err } defer cursor.Close(ctx) // 解析结果 for cursor.Next(ctx) { var result entity.UserWithdrawalResp if err := cursor.Decode(&result); err != nil { return nil, err } results = append(results, &result) } if err := cursor.Err(); err != nil { return nil, err } return results, nil } // WithdrawalStatus 更新提现状态 func (s *Synthesis) WithdrawalStatus(req *entity.UserWithdrawalStatus) error { ctx, cancel := context.WithTimeout(context.Background(), 100*time.Second) defer cancel() collection := mdb.MDB.Collection("CashOutRecord") _, err := collection.UpdateOne(ctx, bson.M{"userName": req.UserName}, bson.M{"$set": bson.M{"status": req.Status}}) if err != nil { return err } return nil } // FindUserCountryCount 查询用户国家分布 // // 返回值为 UserCountryResp 的切片和错误。 func (s *Synthesis) FindUserCountryCount() ([]*entity.UserCountryResp, error) { // 设置超时的上下文 ctx, cancel := context.WithTimeout(context.Background(), 100*time.Second) defer cancel() // 获取数据库的集合 collection := s.db.Collection("user_country_count") // 设置百分比阈值 threshold := 1 // 执行聚合查询 var results []*entity.UserCountryResp cursor, err := collection.Find(ctx, bson.M{}, options.Find()) if err != nil { return nil, err } defer cursor.Close(ctx) // 解析结果 for cursor.Next(ctx) { var result model.UserCountryCount if err := cursor.Decode(&result); err != nil { return nil, err } results = append(results, &entity.UserCountryResp{ Country: result.Country, IPCount: result.IPCount, Percentage: result.Percentage, }) } if err := cursor.Err(); err != nil { return nil, err } // 根据阈值过滤结果 otherCount := 0 otherPercentage := 0 filteredResults := make([]*entity.UserCountryResp, 0) for _, r := range results { if r.Percentage >= threshold { filteredResults = append(filteredResults, r) } else { otherCount += r.IPCount otherPercentage += r.Percentage } } // 将其他国家添加到过滤后的结果中 if otherCount > 0 { filteredResults = append(filteredResults, &entity.UserCountryResp{ Country: "other", IPCount: otherCount, }) } return filteredResults, nil } // FindUserRetention UserRetentionResp 用户留存率 // 1. 获取指定日期范围内的注册用户数量 // 2. 获取指定日期范围内的活跃用户数量 // 3. 计算留存率 // 4. 返回结果 func (s *Synthesis) FindUserRetention(req *entity.UserRetentionReq) ([]*entity.UserRetentionResp, error) { ctx, cancel := context.WithTimeout(context.Background(), 100*time.Second) defer cancel() collection := s.db.Collection("user_reg_count") // 构建过滤器 filter := bson.M{} if req.StartTime != 0 { filter["registration_date"] = bson.M{ "$gte": req.StartTime, "$lte": req.EndTime, } // 日期范围 } // 设置分页选项 findOptions := options.Find() findOptions.SetSkip(int64((req.Page - 1) * req.Size)) findOptions.SetLimit(int64(req.Size)) // 查询数据 var results []*entity.UserRetentionResp cursor, err := collection.Find(ctx, filter, findOptions) if err != nil { return nil, err } defer cursor.Close(ctx) // 解析结果 for cursor.Next(ctx) { var result model.UserRetentionData if err := cursor.Decode(&result); err != nil { return nil, err } results = append(results, &entity.UserRetentionResp{ UserRetentionData: &result, }) } if err := cursor.Err(); err != nil { return nil, err } return results, nil } // FindUserLevel 用户等级统计 func (s *Synthesis) FindUserLevel() ([]*entity.UserLevelCountResp, error) { ctx, cancel := context.WithTimeout(context.Background(), 100*time.Second) defer cancel() collection := mdb.MDB.Collection("playerLevelStat") // 查询所有文档 cursor, err := collection.Find(ctx, bson.M{}) if err != nil { return nil, err } defer cursor.Close(ctx) var results []*entity.UserLevelCountResp var reData []*models.PlayerLevelStat for cursor.Next(ctx) { var result models.PlayerLevelStat if err := cursor.Decode(&result); err != nil { return nil, err } reData = append(reData, &result) } if err := cursor.Err(); err != nil { return nil, err } dataMap := make(map[string]int) for _, v := range reData { for key, v1 := range v.ServerLevel { dataMap[key] += v1 } } for k, v := range dataMap { results = append(results, &entity.UserLevelCountResp{ Level: cast.ToInt(k), UserCount: v, }) } return results, nil }