package v1 import ( "bufio" "context" "designs/app/common/request" "designs/app/common/response" "designs/config" "designs/global" "designs/model" "designs/service" "designs/utils" "encoding/json" "fmt" "github.com/gin-gonic/gin" "go.mongodb.org/mongo-driver/v2/bson" "go.mongodb.org/mongo-driver/v2/mongo/options" "math" "math/big" "os" "path/filepath" "strconv" "strings" "time" ) // 总览 func Summary(c *gin.Context) { form := request.Check(c, &struct { Gid string `form:"gid" json:"gid" binding:"required"` Pf string `form:"pf" json:"pf" binding:"required"` }{}) start := time.Now() //查询用户总数 var userCount int64 err := global.App.DB.Table("user"). Where("gid", form.Gid). Where("pf", form.Pf). Count(&userCount).Error if err != nil { response.Fail(c, 1001, err.Error()) return } fmt.Println(time.Since(start)) //查询近七日活跃总数 now := time.Now() sevenDayAgo := now.AddDate(0, 0, -7) thirtyDayAgo := now.AddDate(0, 0, -30) var activeUserCount7 int64 err = global.App.DB.Table("user_login"). Where("gid", form.Gid). Where("pf", form.Pf). Where("loginTime", ">=", sevenDayAgo). Where("loginTime", "<=", now). Distinct("userId"). Count(&activeUserCount7).Error if err != nil { response.Fail(c, 1001, err.Error()) return } fmt.Println(time.Since(start)) var activeUserCount30 int64 err = global.App.DB.Table("user_login"). Where("gid", form.Gid). Where("pf", form.Pf). Where("loginTime", ">=", thirtyDayAgo). Where("loginTime", "<=", now). Distinct("userId"). Count(&activeUserCount30).Error if err != nil { response.Fail(c, 1001, err.Error()) return } fmt.Println(time.Since(start)) //从redis中读取缓存 var avgTimeString string avgTimeKey := fmt.Sprintf("%s|%s|avgTime", form.Gid, form.Pf) avgTimeString, _ = global.App.Redis.Get(context.Background(), avgTimeKey).Result() if avgTimeString == "" { //查询 近7日单设备日均使用时长 res, err := service.UserOnlineSummary(form.Gid, form.Pf, "", sevenDayAgo.Format("2006-01-02 15:04:05"), now.Format("2006-01-02 15:04:05")) if err != nil { response.Fail(c, 1001, err.Error()) return } var avgTime int for _, v := range res { avgTime = avgTime + int(v) } if avgTime != 0 { avgTime = int(math.Round(float64(avgTime / len(res)))) avgTimeString = utils.TimeStampToMDS(avgTime) } else { avgTimeString = "00.00" } global.App.Redis.Set(context.Background(), avgTimeKey, avgTimeString, time.Second*3000) } response.Success(c, gin.H{ "data": map[string]interface{}{ "userCount": userCount, "activeUserCount7": activeUserCount7, "activeUserCount30": activeUserCount30, "activeUserCount7Time": avgTimeString, }, }) } // 时段分布 func TimeDistributionData(c *gin.Context) { form := request.Check(c, &struct { Gid string `form:"gid" json:"gid" binding:"required"` Pf string `form:"pf" json:"pf" binding:"required"` Type int `form:"type" json:"type" binding:"required"` }{}) var data interface{} if form.Type == 1 { //新增用户 todayTimeDistribution, yesterdayTimeDistribution, yesterdayCount, todayCount, yesterdayThisTimeCount, err := service.GetRegisterTimeDistribution(form.Pf, form.Gid) if err != nil { response.Fail(c, 1001, err.Error()) return } data = map[string]interface{}{ "today": todayTimeDistribution, "yesterday": yesterdayTimeDistribution, "yesterdayCount": yesterdayCount, "yesterdayThisTimeCount": yesterdayThisTimeCount, "todayCount": todayCount, } } else if form.Type == 2 { //活跃设备 todayTimeDistribution, yesterdayTimeDistribution, yesterdayCount, todayCount, yesterdayThisTimeCount, err := service.GetActiveTimeDistribution(form.Pf, form.Gid) if err != nil { response.Fail(c, 1001, err.Error()) return } data = map[string]interface{}{ "today": todayTimeDistribution, "yesterday": yesterdayTimeDistribution, "yesterdayCount": yesterdayCount, "yesterdayThisTimeCount": yesterdayThisTimeCount, "todayCount": todayCount, } } else if form.Type == 3 { //启动次数 todayTimeDistribution, yesterdayTimeDistribution, yesterdayCount, todayCount, yesterdayThisTimeCount, err := service.GetActionDistribution(form.Pf, form.Gid) if err != nil { response.Fail(c, 1001, err.Error()) return } data = map[string]interface{}{ "today": todayTimeDistribution, "yesterday": yesterdayTimeDistribution, "yesterdayCount": yesterdayCount, "yesterdayThisTimeCount": yesterdayThisTimeCount, "todayCount": todayCount, } } else { response.Fail(c, 1003, "type错误") return } response.Success(c, gin.H{ "data": data, }) } // 30日趋势 func MouthDistributionData(c *gin.Context) { form := request.Check(c, &struct { Gid string `form:"gid" json:"gid" binding:"required"` Pf string `form:"pf" json:"pf" binding:"required"` Type int `form:"type" json:"type" binding:"required"` }{}) now := time.Now() EndTime := now.AddDate(0, 0, 1).Format("2006-01-02") StartTime := now.AddDate(0, 0, -29).Format("2006-01-02") data := make(map[string]interface{}) if form.Type == 1 { //查询新增设备趋势图 TimeDistribution, count, avg, err := service.GetRegisterDayDistribution(form.Pf, form.Gid, StartTime, EndTime) if err != nil { response.Fail(c, 1001, err.Error()) return } data["timeDistribution"] = TimeDistribution data["count"] = count data["avg"] = avg } else if form.Type == 2 { //查询活跃用户趋势图 TimeDistribution, count, avg, err := service.GetActiveDayDistribution(form.Pf, form.Gid, StartTime, EndTime) if err != nil { response.Fail(c, 1001, err.Error()) return } data["timeDistribution"] = TimeDistribution data["count"] = count data["avg"] = avg } else if form.Type == 3 { //查询启动次数 TimeDistribution, count, avg, err := service.GetActiveMouthDistribution(form.Pf, form.Gid, StartTime, EndTime) if err != nil { response.Fail(c, 1001, err.Error()) return } data["timeDistribution"] = TimeDistribution data["count"] = count data["avg"] = avg } else if form.Type == 4 { //查询单用户使用时长 TimeDistribution, count, avg, err := service.GetActiveMouthDistribution(form.Pf, form.Gid, StartTime, EndTime) if err != nil { response.Fail(c, 1001, err.Error()) return } data["timeDistribution"] = TimeDistribution data["count"] = count data["avg"] = avg } else if form.Type == 5 { //查询用户留存率 //todo } else { response.Fail(c, 1003, "type错误") return } response.Success(c, gin.H{ "data": data, }) } // 用户趋势 总览 func UserTrendsOverview(c *gin.Context) { form := request.Check(c, &struct { Gid string `form:"gid" json:"gid" binding:"required"` Pf string `form:"pf" json:"pf" binding:"required"` StartTime string `form:"startTime" json:"startTime" binding:"required"` EndTime string `form:"endTime" json:"endTime" binding:"required"` }{}) start := time.Now() //查询用户新增 var registerCount int64 err := global.App.DB.Table("user"). Where("gid", form.Gid). Where("pf", form.Pf). Where("createdAt", ">=", form.StartTime). Where("createdAt", "<=", form.EndTime). Count(®isterCount).Error if err != nil { response.Fail(c, 1001, err.Error()) return } fmt.Println(time.Since(start)) //查询活跃设备 var activeCount int64 //sql := "SELECT COUNT(DISTINCT(`userId`)) FROM `user_online` USE INDEX(date) WHERE gid = ? AND pf = ? AND date >= ? AND date <= ?" //err = global.App.DB.Raw(sql, form.Gid, form.Pf, strings.Replace(form.StartTime, "-", "", 5), strings.Replace(form.EndTime, "-", "", 5)).Count(&activeCount).Error UserLoginBydDay := utils.GetTimeDayDate(form.StartTime, form.EndTime) //用户分别是在哪天注册的 var activeLog [][]int //逐天读取每天活跃的用户数据 for k := range UserLoginBydDay { activeLog = append(activeLog, service.GetLocalActiveLog(form.Gid, form.Pf, k)) } activeLogCount := utils.UnionOfSubArrays(activeLog) activeCount = int64(len(activeLogCount)) //查询启动次数 var loginCount int64 err = global.App.DB.Table("user_login"). Where("gid", form.Gid). Where("pf", form.Pf). Where("loginTime", ">=", form.StartTime). Where("loginTime", "<=", form.EndTime). Count(&loginCount).Error if err != nil { response.Fail(c, 1001, err.Error()) return } fmt.Println(time.Since(start)) //查询平均启动时长 //查询活跃用户月趋势图 _, _, activeTime, err := service.GetActiveMouthDistribution(form.Pf, form.Gid, form.StartTime, form.EndTime) if err != nil { response.Fail(c, 1001, err.Error()) return } //查询 DAU/MAU //todo 查询方式需要更新 dauMau := 0.3 response.Success(c, gin.H{ "data": map[string]interface{}{ "registerCount": registerCount, "activeCount": activeCount, "loginCount": loginCount, "activeTime": activeTime, "dauMau": dauMau, }, }) } // 数据趋势 func DataTrades(c *gin.Context) { form := request.Check(c, &struct { Gid string `form:"gid" json:"gid" binding:"required"` Pf string `form:"pf" json:"pf" binding:"required"` StartTime string `form:"startTime" json:"startTime" binding:"required"` EndTime string `form:"endTime" json:"endTime" binding:"required"` Type int `form:"type" json:"type" binding:"required"` }{}) data := make(map[string]interface{}) form.EndTime = form.EndTime + " 23:59:59" if form.Type == 1 { //查询新增设备趋势图 TimeDistribution, count, avg, err := service.GetRegisterDayDistribution(form.Pf, form.Gid, form.StartTime, form.EndTime) if err != nil { response.Fail(c, 1001, err.Error()) return } data["imeDistribution"] = TimeDistribution data["count"] = count data["avg"] = avg } else if form.Type == 2 { //查询活跃用户趋势图 TimeDistribution, count, avg, err := service.GetActiveDayDistribution(form.Pf, form.Gid, form.StartTime, form.EndTime) if err != nil { response.Fail(c, 1001, err.Error()) return } data["imeDistribution"] = TimeDistribution data["count"] = count data["avg"] = avg } else if form.Type == 3 { //查询活跃用户周趋势图 TimeDistribution, count, avg, err := service.GetActiveWeekDistribution(form.Pf, form.Gid, form.StartTime, form.EndTime) if err != nil { response.Fail(c, 1001, err.Error()) return } data["imeDistribution"] = TimeDistribution data["count"] = count data["avg"] = avg } else if form.Type == 4 { //查询活跃用户月趋势图 TimeDistribution, count, avg, err := service.GetActiveMouthDistribution(form.Pf, form.Gid, form.StartTime, form.EndTime) if err != nil { response.Fail(c, 1001, err.Error()) return } data["imeDistribution"] = TimeDistribution data["count"] = count data["avg"] = avg } else if form.Type == 5 { //查询启动次数 TimeDistribution, count, avg, err := service.GetActiveMouthDistribution(form.Pf, form.Gid, form.StartTime, form.EndTime) if err != nil { response.Fail(c, 1001, err.Error()) return } data["imeDistribution"] = TimeDistribution data["count"] = count data["avg"] = avg } else if form.Type == 6 { //查询平均启动时间 TimeDistribution, count, avg, err := service.UserOnlineSummaryByDay(form.Gid, form.Pf, form.StartTime, form.EndTime) if err != nil { response.Fail(c, 1001, err.Error()) return } data["imeDistribution"] = TimeDistribution data["count"] = count data["avg"] = avg } else { response.Fail(c, 1003, "type 错误") return } response.Success(c, gin.H{ "data": data, }) } // 数据趋势的整合 func DataTradesDetail(c *gin.Context) { form := request.Check(c, &struct { Gid string `form:"gid" json:"gid" binding:"required"` Pf string `form:"pf" json:"pf" binding:"required"` StartTime string `form:"startTime" json:"startTime" binding:"required"` EndTime string `form:"endTime" json:"endTime" binding:"required"` }{}) form.EndTime = form.EndTime + " 23:59:59" type dayData struct { NewUser int `json:"newUser"` ActiveUser int `json:"activeUser"` ActiveUserWeek int `json:"activeUserWeek"` ActiveUserMouth int `json:"activeUserMouth"` ActiveStart int `json:"activeStart"` AvgTime int `json:"avgTime"` } var data = make(map[string]dayData) start := time.Now() //查询新增设备趋势图 NewUser, _, _, err := service.GetRegisterDayDistribution(form.Pf, form.Gid, form.StartTime, form.EndTime) if err != nil { response.Fail(c, 1001, err.Error()) return } fmt.Println(time.Since(start)) //查询活跃用户趋势图 ActiveUser, _, _, err := service.GetActiveDayDistribution(form.Pf, form.Gid, form.StartTime, form.EndTime) if err != nil { response.Fail(c, 1001, err.Error()) return } fmt.Println(time.Since(start)) //查询活跃用户周趋势图 ActiveUserWeek, _, _, err := service.GetActiveWeekDistribution(form.Pf, form.Gid, form.StartTime, form.EndTime) if err != nil { response.Fail(c, 1001, err.Error()) return } fmt.Println(time.Since(start)) //查询活跃用户月趋势图 ActiveUserMouth, _, _, err := service.GetActiveMouthDistribution(form.Pf, form.Gid, form.StartTime, form.EndTime) if err != nil { response.Fail(c, 1001, err.Error()) return } fmt.Println(time.Since(start)) //查询启动次数 ActiveStart, _, _, err := service.GetActiveMouthDistribution(form.Pf, form.Gid, form.StartTime, form.EndTime) if err != nil { response.Fail(c, 1001, err.Error()) return } fmt.Println(time.Since(start)) //查询平均启动时间 AvgTime, _, _, err := service.UserOnlineSummaryByDay(form.Gid, form.Pf, form.StartTime, form.EndTime) if err != nil { response.Fail(c, 1001, err.Error()) return } for k := range AvgTime { data[k] = dayData{ NewUser: NewUser[k], ActiveUser: ActiveUser[k], ActiveUserWeek: ActiveUserWeek[k], ActiveUserMouth: ActiveUserMouth[k], ActiveStart: ActiveStart[k], AvgTime: AvgTime[k], } } response.Success(c, gin.H{ "data": data, }) } func OnlineToFile(c *gin.Context) { service.OnlineToFile() //now := time.Now() //for i := 1; i <= 60; i++ { // lastDay := now.AddDate(0, 0, -i).Format("20060102") // crons.AdsDataSummary(lastDay) //} response.Success(c, gin.H{}) } func RemainDataBydDay(c *gin.Context) { form := request.Check(c, &struct { Gid string `form:"gid" json:"gid" binding:"required"` Pf string `form:"pf" json:"pf" binding:"required"` StartTime string `form:"startTime" json:"startTime" binding:"required"` EndTime string `form:"endTime" json:"endTime" binding:"required"` Type int `form:"type" json:"type" binding:"required"` }{}) //data, err := service.RemainDataBydDay(form.Type, form.Pf, form.Gid, form.StartTime, form.EndTime) //if err != nil { // response.Fail(c, 1001, err.Error()) // return //} data, err := service.RemainDataBydDayNew(form.Type, form.Pf, form.Gid, form.StartTime, form.EndTime) if err != nil { response.Fail(c, 1001, err.Error()) return } response.Success(c, gin.H{ "data": data, }) } type AdData struct { Pid string `json:"pid"` Aid string `json:"aid"` Cid string `json:"cid"` ReportUrl string `json:"reportUrl"` Reported bool `json:"reported"` Duration int64 `json:"duration"` AdReqCount uint8 `json:"adReqCount"` AdEposedcount uint8 `json:"adEposedcount"` CreateTime int `json:"createTime"` } type UserBehavior struct { Id string `bson:"_id,omitempty"` Gid string `bson:"gid" json:"gid"` Pf string `bson:"pf" json:"pf"` OpenId string `bson:"openId" json:"openId"` RelatedAid int64 `bson:"relatedAid" json:"relatedAid"` //目前关联的aid TotalDuration int `bson:"totalDuration" json:"totalDuration"` TotalAdReqCount int `bson:"totalAdReqCount" json:"totalAdReqCount"` TotalAdEposedCount int `bson:"totalAdEposedCount" json:"totalAdEposedCount"` CreateDate string `bson:"createDate" json:"createDate"` CreateTime int `json:"createTime" bson:"createTime"` StartNum int `bson:"startNum" json:"startNum"` ActiveStatus bool `bson:"activeStatus" json:"activeStatus"` //激活状态 ConversionStatus bool `bson:"conversionStatus" json:"conversionStatus"` //转化状态 RemainData map[string]string `json:"remainData" bson:"remainData"` //留存数据 } type AdRelated struct { Id string `bson:"_id" json:"_id"` UserId string `bson:"userId" json:"userId"` Aid int64 `json:"aid" bson:"aid"` //广告的推广计划id,即广告ID,广告平台配置落地页参数 Cid string `json:"cid" bson:"cid"` //openid的用户点击aid广告进入游戏时的唯一标识,广告平台提供 Pid int64 `json:"pid" bson:"pid"` //广告的项目id(仅巨量引擎存在,腾讯广告时不存在该值),广告平台配置落地页参数 CreateTime int64 `bson:"create_time" json:"createTime"` //当前计划的创建时间 StartNum int `bson:"startNum" json:"startNum"` //启动次数 Revenue float32 `bson:"revenue" json:"revenue"` //当日预估收益 Duration int64 `bson:"duration" json:"duration"` //当日在线时长 ReqCount int `bson:"req_count" json:"req_count"` //当日的激励视频广告请求次数 ExpCount int `bson:"exp_count" json:"exp_count"` //当日的激励视频广告曝光次数 } type BehaviorFilter struct { Gt int `json:"gt"` Gte int `json:"gte"` Lte int `json:"lte"` Lt int `json:"lt"` Ne int `json:"ne"` //$gt 大于 //$gte:大于或等于 //$lt:小于 //$lte:小于或等于 //$ne:不等于 } func BehaviorList(c *gin.Context) { form := request.Check(c, &struct { Gid string `form:"gid" json:"gid" binding:"required"` Pf string `form:"pf" json:"pf" binding:"required"` OpenId string `form:"openId" json:"openId" binding:""` Offset int `form:"offset" json:"offset" binding:""` Limit int `form:"limit" json:"limit" binding:""` ActiveStatus string `form:"activeStatus" json:"activeStatus" binding:""` //all true false ConversionStatus string `form:"conversionStatus" json:"conversionStatus" binding:""` //all true false AdFromCount interface{} `form:"adFromCount" json:"adFromCount" binding:""` TotalDuration interface{} `form:"totalDuration" json:"totalDuration" binding:""` TotalAdReqCount interface{} `form:"totalAdReqCount" json:"totalAdReqCount" binding:""` TotalAdEposedCount interface{} `form:"totalAdEposedCount" json:"totalAdEposedCount" binding:""` CreateTime interface{} `form:"createTime" json:"createTime" binding:""` StartNum interface{} `form:"startNum" json:"startNum" binding:""` }{}) collection := global.App.MongoDB.Database("chunhao").Collection("userBehavior") ctx := context.Background() filter := bson.M{"gid": form.Gid} if form.Pf != "" { filter["pf"] = form.Pf } if form.OpenId != "" { filter["openId"] = bson.M{"$regex": form.OpenId} } if form.ActiveStatus == "true" { filter["activeStatus"] = true } else if form.ActiveStatus == "false" { filter["activeStatus"] = false } if form.ActiveStatus == "true" { filter["activeStatus"] = true } else if form.ActiveStatus == "false" { filter["activeStatus"] = false } if form.AdFromCount != nil { fmt.Println(form.AdFromCount) marsh, _ := json.Marshal(form.AdFromCount) var adFromCount BehaviorFilter json.Unmarshal(marsh, &adFromCount) filters := bson.M{} if adFromCount.Gt != 0 { filters["$gt"] = adFromCount.Gt } if adFromCount.Gte != 0 { filters["$gte"] = adFromCount.Gte } if adFromCount.Lte != 0 { filters["$lte"] = adFromCount.Lte } if adFromCount.Lt != 0 { filters["$lt"] = adFromCount.Lt } if adFromCount.Ne != 0 { filters["$ne"] = adFromCount.Ne } if len(filters) > 0 { filter["adFromCount"] = filters } } if form.TotalAdReqCount != nil { marsh, _ := json.Marshal(form.TotalAdReqCount) var totalAdReqCount BehaviorFilter json.Unmarshal(marsh, &totalAdReqCount) filters := bson.M{} if totalAdReqCount.Gt != 0 { filters["$gt"] = totalAdReqCount.Gt } if totalAdReqCount.Gte != 0 { filters["$gte"] = totalAdReqCount.Gte } if totalAdReqCount.Lte != 0 { filters["$lte"] = totalAdReqCount.Lte } if totalAdReqCount.Lt != 0 { filters["$lt"] = totalAdReqCount.Lt } if totalAdReqCount.Ne != 0 { filters["$ne"] = totalAdReqCount.Ne } if len(filters) > 0 { filter["totalAdReqCount"] = filters } } if form.TotalAdEposedCount != nil { marsh, _ := json.Marshal(form.TotalAdEposedCount) var totalAdEposedCount BehaviorFilter json.Unmarshal(marsh, &totalAdEposedCount) filters := bson.M{} if totalAdEposedCount.Gt != 0 { filters["$gt"] = totalAdEposedCount.Gt } if totalAdEposedCount.Gte != 0 { filters["$gte"] = totalAdEposedCount.Gte } if totalAdEposedCount.Lte != 0 { filters["$lte"] = totalAdEposedCount.Lte } if totalAdEposedCount.Lt != 0 { filters["$lt"] = totalAdEposedCount.Lt } if totalAdEposedCount.Ne != 0 { filters["$ne"] = totalAdEposedCount.Ne } if len(filters) > 0 { filter["totalAdEposedCount"] = filters } } if form.CreateTime != nil { marsh, _ := json.Marshal(form.CreateTime) var totalAdEposedCount BehaviorFilter json.Unmarshal(marsh, &totalAdEposedCount) filters := bson.M{} if totalAdEposedCount.Gt != 0 { filters["$gt"] = totalAdEposedCount.Gt } if totalAdEposedCount.Gte != 0 { filters["$gte"] = totalAdEposedCount.Gte } if totalAdEposedCount.Lte != 0 { filters["$lte"] = totalAdEposedCount.Lte } if totalAdEposedCount.Lt != 0 { filters["$lt"] = totalAdEposedCount.Lt } if totalAdEposedCount.Ne != 0 { filters["$ne"] = totalAdEposedCount.Ne } if len(filters) > 0 { filter["createTime"] = filters } } if form.StartNum != nil { marsh, _ := json.Marshal(form.StartNum) var totalAdEposedCount BehaviorFilter json.Unmarshal(marsh, &totalAdEposedCount) filters := bson.M{} if totalAdEposedCount.Gt != 0 { filters["$gt"] = totalAdEposedCount.Gt } if totalAdEposedCount.Gte != 0 { filters["$gte"] = totalAdEposedCount.Gte } if totalAdEposedCount.Lte != 0 { filters["$lte"] = totalAdEposedCount.Lte } if totalAdEposedCount.Lt != 0 { filters["$lt"] = totalAdEposedCount.Lt } if totalAdEposedCount.Ne != 0 { filters["$ne"] = totalAdEposedCount.Ne } if len(filters) > 0 { filter["startNum"] = filters } } if form.TotalDuration != nil { marsh, _ := json.Marshal(form.TotalDuration) var totalAdEposedCount BehaviorFilter json.Unmarshal(marsh, &totalAdEposedCount) filters := bson.M{} if totalAdEposedCount.Gt != 0 { filters["$gt"] = totalAdEposedCount.Gt } if totalAdEposedCount.Gte != 0 { filters["$gte"] = totalAdEposedCount.Gte } if totalAdEposedCount.Lte != 0 { filters["$lte"] = totalAdEposedCount.Lte } if totalAdEposedCount.Lt != 0 { filters["$lt"] = totalAdEposedCount.Lt } if totalAdEposedCount.Ne != 0 { filters["$ne"] = totalAdEposedCount.Ne } if len(filters) > 0 { filter["totalDuration"] = filters } } option := options.Find() option.SetLimit(int64(form.Limit)) option.SetSkip(int64(form.Offset)) cur, err := collection.Find(ctx, filter, option) if err != nil { response.Fail(c, 1001, err.Error()) return } count, err := collection.CountDocuments(ctx, filter) if err != nil { response.Fail(c, 1001, err.Error()) return } var data []UserBehavior err = cur.All(ctx, &data) if err != nil { response.Fail(c, 1001, err.Error()) return } response.Success(c, gin.H{ "data": data, "count": count, }) } func AdRelatedList(c *gin.Context) { form := request.Check(c, &struct { //Gid string `form:"gid" json:"gid" binding:"required"` //Pf string `form:"pf" json:"pf" binding:"required"` //OpenId string `form:"search" json:"search" binding:""` Offset int `form:"offset" json:"offset" binding:""` Limit int `form:"limit" json:"limit" binding:""` Pid string `form:"pid" json:"pid" binding:""` Aid string `form:"aid" json:"aid" binding:""` Cid string `form:"cid" json:"cid" binding:""` CreateTime interface{} `form:"createTime" json:"createTime" binding:""` StartNum interface{} `form:"startNum" json:"startNum" binding:""` Revenue interface{} `form:"revenue" json:"revenue" binding:""` Duration interface{} `form:"duration" json:"duration" binding:""` ReqCount interface{} `form:"reqCount" json:"reqCount" binding:""` ExpCount interface{} `form:"expCount" json:"expCount" binding:""` }{}) collection := global.App.MongoDB.Database("chunhao").Collection("adRelated") ctx := context.Background() filter := bson.M{} if form.Pid != "" { filter["pid"] = form.Pid } if form.Aid != "" { filter["aid"] = form.Aid } if form.Cid != "" { filter["cid"] = form.Cid } if form.CreateTime != nil { marsh, _ := json.Marshal(form.CreateTime) var totalAdEposedCount BehaviorFilter json.Unmarshal(marsh, &totalAdEposedCount) filters := bson.M{} if totalAdEposedCount.Gt != 0 { filters["$gt"] = totalAdEposedCount.Gt } if totalAdEposedCount.Gte != 0 { filters["$gte"] = totalAdEposedCount.Gte } if totalAdEposedCount.Lte != 0 { filters["$lte"] = totalAdEposedCount.Lte } if totalAdEposedCount.Lt != 0 { filters["$lt"] = totalAdEposedCount.Lt } if totalAdEposedCount.Ne != 0 { filters["$ne"] = totalAdEposedCount.Ne } if len(filters) > 0 { filter["createTime"] = filters } } if form.StartNum != nil { marsh, _ := json.Marshal(form.StartNum) var totalAdEposedCount BehaviorFilter json.Unmarshal(marsh, &totalAdEposedCount) filters := bson.M{} if totalAdEposedCount.Gt != 0 { filters["$gt"] = totalAdEposedCount.Gt } if totalAdEposedCount.Gte != 0 { filters["$gte"] = totalAdEposedCount.Gte } if totalAdEposedCount.Lte != 0 { filters["$lte"] = totalAdEposedCount.Lte } if totalAdEposedCount.Lt != 0 { filters["$lt"] = totalAdEposedCount.Lt } if totalAdEposedCount.Ne != 0 { filters["$ne"] = totalAdEposedCount.Ne } if len(filters) > 0 { filter["startNum"] = filters } } if form.Revenue != nil { marsh, _ := json.Marshal(form.Revenue) var totalAdEposedCount BehaviorFilter json.Unmarshal(marsh, &totalAdEposedCount) filters := bson.M{} if totalAdEposedCount.Gt != 0 { filters["$gt"] = totalAdEposedCount.Gt } if totalAdEposedCount.Gte != 0 { filters["$gte"] = totalAdEposedCount.Gte } if totalAdEposedCount.Lte != 0 { filters["$lte"] = totalAdEposedCount.Lte } if totalAdEposedCount.Lt != 0 { filters["$lt"] = totalAdEposedCount.Lt } if totalAdEposedCount.Ne != 0 { filters["$ne"] = totalAdEposedCount.Ne } if len(filters) > 0 { filter["revenue"] = filters } } if form.Duration != nil { marsh, _ := json.Marshal(form.Duration) var totalAdEposedCount BehaviorFilter json.Unmarshal(marsh, &totalAdEposedCount) filters := bson.M{} if totalAdEposedCount.Gt != 0 { filters["$gt"] = totalAdEposedCount.Gt } if totalAdEposedCount.Gte != 0 { filters["$gte"] = totalAdEposedCount.Gte } if totalAdEposedCount.Lte != 0 { filters["$lte"] = totalAdEposedCount.Lte } if totalAdEposedCount.Lt != 0 { filters["$lt"] = totalAdEposedCount.Lt } if totalAdEposedCount.Ne != 0 { filters["$ne"] = totalAdEposedCount.Ne } if len(filters) > 0 { filter["duration"] = filters } } if form.ReqCount != nil { marsh, _ := json.Marshal(form.ReqCount) var totalAdEposedCount BehaviorFilter json.Unmarshal(marsh, &totalAdEposedCount) filters := bson.M{} if totalAdEposedCount.Gt != 0 { filters["$gt"] = totalAdEposedCount.Gt } if totalAdEposedCount.Gte != 0 { filters["$gte"] = totalAdEposedCount.Gte } if totalAdEposedCount.Lte != 0 { filters["$lte"] = totalAdEposedCount.Lte } if totalAdEposedCount.Lt != 0 { filters["$lt"] = totalAdEposedCount.Lt } if totalAdEposedCount.Ne != 0 { filters["$ne"] = totalAdEposedCount.Ne } if len(filters) > 0 { filter["reqCount"] = filters } } if form.ExpCount != nil { marsh, _ := json.Marshal(form.ExpCount) var totalAdEposedCount BehaviorFilter json.Unmarshal(marsh, &totalAdEposedCount) filters := bson.M{} if totalAdEposedCount.Gt != 0 { filters["$gt"] = totalAdEposedCount.Gt } if totalAdEposedCount.Gte != 0 { filters["$gte"] = totalAdEposedCount.Gte } if totalAdEposedCount.Lte != 0 { filters["$lte"] = totalAdEposedCount.Lte } if totalAdEposedCount.Lt != 0 { filters["$lt"] = totalAdEposedCount.Lt } if totalAdEposedCount.Ne != 0 { filters["$ne"] = totalAdEposedCount.Ne } if len(filters) > 0 { filter["expCount"] = filters } } option := options.Find() option.SetLimit(int64(form.Limit)) option.SetSkip(int64(form.Offset)) cur, err := collection.Find(ctx, filter, option) if err != nil { response.Fail(c, 1001, err.Error()) return } count, err := collection.CountDocuments(ctx, filter) if err != nil { response.Fail(c, 1001, err.Error()) return } var data []AdRelated err = cur.All(ctx, &data) if err != nil { response.Fail(c, 1001, err.Error()) return } response.Success(c, gin.H{ "data": data, "count": count, }) } // ConversionCondition 转化条件 type ConversionCondition struct { Id string `bson:"_id" json:"id"` Gid string `bson:"gid" json:"gid"` Pid *big.Int `bson:"pid" json:"pid"` Aid *big.Int `bson:"aid" json:"aid"` Type string `bson:"type" json:"type"` StartNum int `bson:"start_num" json:"start_num"` //启动次数 EstimatedRevenue float32 `bson:"revenue" json:"revenue"` //当日预估收益 Duration int64 `bson:"duration" json:"duration"` //当日在线时长 ReqRewardedAd int `bson:"req_count" json:"req_count"` //当日的激励视频广告请求次数 ExpRewardedAd int `bson:"exp_count" json:"exp_count"` //当日的激励视频广告曝光次数 } func SetGameCondition(c *gin.Context) { form := request.Check(c, &struct { Gid string `form:"gid" json:"gid" binding:"required"` Pid string `form:"pid" json:"pid" binding:""` Aid string `form:"aid" json:"aid" binding:""` Type string `form:"type" json:"type" binding:"required"` StartNum int `form:"start_num" json:"start_num" binding:""` EstimatedRevenue float32 `form:"revenue" json:"revenue" binding:""` Duration int64 `form:"duration" json:"duration" binding:""` ReqRewardedAd int `form:"req_count" json:"req_count" binding:""` ExpRewardedAd int `form:"exp_count" json:"exp_count" binding:""` }{}) id := fmt.Sprintf("%s|%s|%s|%s", form.Gid, form.Pid, form.Aid, form.Type) PidInt := new(big.Int) PidInt.SetString(form.Pid, 10) AidInt := new(big.Int) AidInt.SetString(form.Aid, 10) collection := global.App.MongoDB.Database("chunhao").Collection("conversionCondition") filter := bson.M{"_id": id} var conversionCondition ConversionCondition err := collection.FindOne(context.TODO(), filter).Decode(&conversionCondition) //if err != nil { // response.Fail(c, 1002, err.Error()) // return //} if conversionCondition.Id != "" { //存在,更新 update := bson.M{ "$set": struct { StartNum int `bson:"start_num"` //启动次数 EstimatedRevenue float32 `bson:"revenue"` //当日预估收益 Duration int64 `bson:"duration"` //当日在线时长 ReqRewardedAd int `bson:"req_count"` //当日的激励视频广告请求次数 ExpRewardedAd int `bson:"exp_count"` //当日的激励视频广告曝光次数 }{ StartNum: form.StartNum, EstimatedRevenue: form.EstimatedRevenue, Duration: form.Duration, ReqRewardedAd: form.ReqRewardedAd, ExpRewardedAd: form.ExpRewardedAd, }, } _, err = collection.UpdateOne(context.TODO(), filter, update) if err != nil { response.Fail(c, 1003, err.Error()) return } } else { //不存在,新增 insert := ConversionCondition{ Id: id, Pid: PidInt, Aid: AidInt, Gid: form.Gid, Type: form.Type, StartNum: form.StartNum, EstimatedRevenue: form.EstimatedRevenue, Duration: form.Duration, ReqRewardedAd: form.ReqRewardedAd, ExpRewardedAd: form.ExpRewardedAd, } _, err = collection.InsertOne(context.TODO(), insert) if err != nil { response.Fail(c, 1001, err.Error()) return } } response.Success(c, gin.H{}) } func GameConditionList(c *gin.Context) { form := request.Check(c, &struct { Gid string `form:"gid" json:"gid" binding:"required"` Pid string `form:"pid" json:"pid" binding:""` Aid string `form:"aid" json:"aid" binding:""` Type string `form:"type" json:"type" binding:""` Offset int `form:"offset" json:"offset" binding:""` Limit int `form:"limit" json:"limit" binding:"required"` }{}) collection := global.App.MongoDB.Database("chunhao").Collection("conversionCondition") filter := bson.M{"gid": form.Gid, "type": form.Type} if form.Type != "" { filter["type"] = form.Type } if form.Pid != "" { filter["pid"] = form.Pid } if form.Aid != "" { filter["aid"] = form.Aid } ctx := context.Background() option := options.Find() option.SetLimit(int64(form.Limit)) option.SetSkip(int64(form.Offset)) cur, err := collection.Find(ctx, filter, option) if err != nil { response.Fail(c, 1001, err.Error()) return } count, err := collection.CountDocuments(ctx, filter) if err != nil { response.Fail(c, 1001, err.Error()) return } var data []ConversionCondition err = cur.All(ctx, &data) if err != nil { response.Fail(c, 1001, err.Error()) return } response.Success(c, gin.H{ "data": data, "count": count, }) } func BehaviorListCake(c *gin.Context) { form := request.Check(c, &struct { Gid string `form:"gid" json:"gid" binding:"required"` Pf string `form:"pf" json:"pf" binding:"required"` ActiveStatus string `form:"activeStatus" json:"activeStatus" binding:""` //all true false ConversionStatus string `form:"conversionStatus" json:"conversionStatus" binding:""` //all true false TotalDuration string `form:"totalDuration" json:"totalDuration" binding:""` TotalAdReqCount string `form:"totalAdReqCount" json:"totalAdReqCount" binding:""` TotalAdEposedCount string `form:"totalAdEposedCount" json:"totalAdEposedCount" binding:""` CreateTime string `json:"createTime" bson:"createTime"` //AdFromCount string `form:"adFromCount" json:"adFromCount" binding:""` //StartNum string `form:"startNum" json:"startNum" binding:""` }{}) collection := global.App.MongoDB.Database("chunhao").Collection("userBehavior") ctx := context.Background() filter := bson.M{"gid": form.Gid} if form.Pf != "" { filter["pf"] = form.Pf } if form.ActiveStatus == "true" { filter["activeStatus"] = true } else if form.ActiveStatus == "false" { filter["activeStatus"] = false } if form.ActiveStatus == "true" { filter["activeStatus"] = true } else if form.ActiveStatus == "false" { filter["activeStatus"] = false } if form.CreateTime != "" { createTime := strings.Split(strings.Replace(form.CreateTime, ",", ",", -1), ",") filters := bson.M{} filters["$gt"], _ = strconv.Atoi(createTime[0]) filters["$lte"], _ = strconv.Atoi(createTime[1]) filter["createTime"] = filters } type resData struct { Count int `json:"count"` Name string `json:"name"` } filterListTotalDuration := make(map[string]bson.M) filterList := make(map[string]bson.M) var data []resData if form.TotalDuration != "" { totalDuration := strings.Split(strings.Replace(form.TotalDuration, ",", ",", -1), ",") for k, _ := range totalDuration { var gt, lte int if k == 0 { gt = 0 lte, _ = strconv.Atoi(totalDuration[k]) } else { gt, _ = strconv.Atoi(totalDuration[k-1]) lte, _ = strconv.Atoi(totalDuration[k]) } filters := bson.M{} filters["$gt"] = gt filters["$lte"] = lte filter1 := utils.DeepCopyMap(filter) filter1["totalDuration"] = filters name := "在线时长:" + strconv.Itoa(gt) + "-" + strconv.Itoa(lte) filterListTotalDuration[name] = filter1 } filters := bson.M{} filters["$gt"], _ = strconv.Atoi(totalDuration[len(totalDuration)-1]) filter["totalDuration"] = filters name := "在线时长:" + totalDuration[len(totalDuration)-1] + "-" + "∞" filterListTotalDuration[name] = filter } if form.TotalAdReqCount != "" && form.TotalAdEposedCount == "" { totalDuration := strings.Split(strings.Replace(form.TotalAdReqCount, ",", ",", -1), ",") for k, _ := range totalDuration { var gt, lte int if k == 0 { gt = 0 lte, _ = strconv.Atoi(totalDuration[k]) } else { gt, _ = strconv.Atoi(totalDuration[k-1]) lte, _ = strconv.Atoi(totalDuration[k]) } filters := bson.M{} filters["$gt"] = gt filters["$lte"] = lte if len(filterListTotalDuration) != 0 { for nameD, filterD := range filterListTotalDuration { filterE := utils.DeepCopyMap(filterD) filterE["totalAdReqCount"] = filters name := nameD + "&&" + "广告观看次数:" + strconv.Itoa(gt) + "-" + strconv.Itoa(lte) filterList[name] = filterE } } else { filter1 := utils.DeepCopyMap(filter) filter1["totalAdReqCount"] = filters name := "广告观看次数:" + strconv.Itoa(gt) + "-" + strconv.Itoa(lte) filterList[name] = filter1 } } filters := bson.M{} filters["$gt"], _ = strconv.Atoi(totalDuration[len(totalDuration)-1]) filter["totalAdReqCount"] = filters if len(filterListTotalDuration) != 0 { for nameD, filterD := range filterListTotalDuration { filterD["totalAdReqCount"] = filters name := nameD + "&&" + "广告观看次数:" + totalDuration[len(totalDuration)-1] + "-" + "∞" filterList[name] = filterD } } else { filter1 := utils.DeepCopyMap(filter) filter["totalAdReqCount"] = filters name := "广告观看次数:" + totalDuration[len(totalDuration)-1] + "-" + "∞" filterList[name] = filter1 } //count, err := collection.CountDocuments(ctx, filter) //if err != nil { // response.Fail(c, 1001, err.Error()) // return //} //data = append(data, resData{ // Count: int(count), // Name: totalDuration[len(totalDuration)-1] + "-" + "∞", //}) } if form.TotalAdEposedCount != "" && form.TotalAdReqCount == "" { totalDuration := strings.Split(strings.Replace(form.TotalAdEposedCount, ",", ",", -1), ",") for k, _ := range totalDuration { var gt, lte int if k == 0 { gt = 0 lte, _ = strconv.Atoi(totalDuration[k]) } else { gt, _ = strconv.Atoi(totalDuration[k-1]) lte, _ = strconv.Atoi(totalDuration[k]) } filters := bson.M{} filters["$gt"] = gt filters["$lte"] = lte if len(filterListTotalDuration) != 0 { for nameD, filterD := range filterListTotalDuration { filterE := utils.DeepCopyMap(filterD) filterE["TotalAdEposedCount"] = filters name := nameD + "&&" + "广告看完次数:" + strconv.Itoa(gt) + "-" + strconv.Itoa(lte) filterList[name] = filterE } } else { filter1 := utils.DeepCopyMap(filter) filter1["TotalAdEposedCount"] = filters name := "广告看完次数:" + strconv.Itoa(gt) + "-" + strconv.Itoa(lte) filterList[name] = filter1 } } filters := bson.M{} filters["$gt"], _ = strconv.Atoi(totalDuration[len(totalDuration)-1]) filter["TotalAdEposedCount"] = filters if len(filterListTotalDuration) != 0 { for nameD, filterD := range filterListTotalDuration { filterD["TotalAdEposedCount"] = filters name := nameD + "&&" + "广告看完次数:" + totalDuration[len(totalDuration)-1] + "-" + "∞" filterList[name] = filterD } } else { filter1 := utils.DeepCopyMap(filter) filter["TotalAdEposedCount"] = filters name := "广告看完次数:" + totalDuration[len(totalDuration)-1] + "-" + "∞" filterList[name] = filter1 } //count, err := collection.CountDocuments(ctx, filter) //if err != nil { // response.Fail(c, 1001, err.Error()) // return //} //data = append(data, resData{ // Count: int(count), // Name: totalDuration[len(totalDuration)-1] + "-" + "∞", //}) } if form.TotalAdEposedCount != "" && form.TotalAdReqCount != "" { response.Fail(c, 1002, "筛选条件无效") return } if len(filterList) == 0 { filterList = filterListTotalDuration } for k, filterC := range filterList { count, _ := collection.CountDocuments(ctx, filterC) data = append(data, resData{ Name: k, Count: int(count), }) } response.Success(c, gin.H{ "data": data, }) } func SplitOnlineData(c *gin.Context) { //只保留最近30天的数据 now := time.Now() for i := 0; i <= 29; i++ { date := now.AddDate(0, 0, -i).Format("2006-01-02") date1 := now.AddDate(0, 0, -i).Format("20060102") var dir string if config.Get("app.local") == "local" { //url = "mongodb://localhost:27017" dir = "storage" } else { dir = "/www/wwwroot/chunhao_receive/storage" } //读取对应的文件夹 dirPath := filepath.Join(dir, date) dateDir, _ := os.ReadDir(dirPath) fmt.Println(dateDir, date) for _, v := range dateDir { var onlineData []model.UserOnlineSplit fileName := v.Name() fileNameSplit := strings.Split(fileName, "_") if len(fileNameSplit) < 2 { continue } last := fileNameSplit[len(fileNameSplit)-1] pf := last[:len(last)-4] gid := strings.TrimRight(fileName, "_"+last) fmt.Println("fileName:", fileName) fmt.Println("gid:", gid) fmt.Println("last:", last) //err1 := DropTable(gid, date1) //fmt.Println(err1) //continue filePath := filepath.Join(dirPath, fileName) file, _ := os.Open(filePath) // 创建 Scanner 对象 scanner := bufio.NewScanner(file) // 逐行读取文件内容 lineNumber := 1 for scanner.Scan() { line := scanner.Text() // 获取当前行内容 lineNumber++ lineData := strings.Split(line, ",") userId, _ := strconv.Atoi(lineData[0]) types, _ := strconv.Atoi(lineData[1]) loc, _ := time.LoadLocation("Asia/Shanghai") LogTime, _ := time.ParseInLocation("2006-01-02 15:04:05", lineData[2], loc) //fmt.Println(LogTime, lineData[2]) onlineData = append(onlineData, model.UserOnlineSplit{ Pf: pf, UserId: userId, Type: types, LogTime: LogTime, }) } file.Close() // 确保函数结束时关闭文件 //数据存入mysql err := InsertOnlineSpilt(gid, date1, onlineData) if err != nil { fmt.Println("插入数据库错误", err) } } fmt.Println(date, "数据归档数据库完成,耗时:", time.Since(now)) } } func InsertOnlineSpilt(gid string, date string, online []model.UserOnlineSplit) error { //先根据date ,gid ,判定存哪个表 tableName := "user_online" + "_" + date + "_" + gid err := global.App.DB.Exec(` CREATE TABLE IF NOT EXISTS ` + tableName + ` ( id int unsigned NOT NULL AUTO_INCREMENT COMMENT '主键', pf varchar(5) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '登录路径', userId int NOT NULL COMMENT '用户ID', type tinyint NOT NULL COMMENT '1:在线 2.下线', logTime timestamp NULL DEFAULT NULL COMMENT '时间', PRIMARY KEY (id) USING BTREE, KEY pf (pf) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci `).Error if err != nil { fmt.Println("创建数据库失败", tableName, err.Error()) return err } err = global.App.DB.Table(tableName).CreateInBatches(&online, 1000).Error if err != nil { return err } return nil } func DropTable(gid string, date string) error { //先根据date ,gid ,判定存哪个表 tableName := "user_online" + "_" + date + "_" + gid sql := "DROP TABLE IF EXISTS " + tableName err := global.App.DB.Exec(sql).Error if err != nil { fmt.Println("创建数据库失败", tableName, err.Error()) return err } return nil }