1、咪咕管理后台用户留存记录(按天)查询优化,先分页再查询;
This commit is contained in:
parent
86d392504b
commit
4dc1acec30
|
@ -1573,73 +1573,72 @@ func (e MiGuDeployService) UserDayRetentionList(c *gin.Context) {
|
|||
// 使用 goroutine 处理并发查询
|
||||
var wg sync.WaitGroup
|
||||
|
||||
// 创建一个 channel 来接收每一天的查询结果
|
||||
//resultChan := make(chan models.MgUserDayRetention, 100)
|
||||
|
||||
// 计算预计查询天数(或月份)
|
||||
var totalDays int
|
||||
// 1. 构建全部查询日期列表
|
||||
var dateList []string
|
||||
if req.OnlyFirstDay {
|
||||
// 当前月的1号
|
||||
now := time.Now()
|
||||
currentMonthFirst := time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, now.Location())
|
||||
// 计算从 nextMonth 到 currentMonthFirst 包含的1号数量
|
||||
totalDays = countFirstDays(nextMonth, currentMonthFirst)
|
||||
// 每月1号
|
||||
for date := nextMonth; !date.After(time.Now()); date = date.AddDate(1, 0, 0) {
|
||||
dateList = append(dateList, date.Format("2006-01-02"))
|
||||
}
|
||||
} else {
|
||||
// 按天查询:计算两个日期之间的天数
|
||||
// 每天
|
||||
startDateTime, _ := time.Parse("2006-01-02", startDate)
|
||||
currentTime, _ := time.Parse("2006-01-02", currentDate)
|
||||
totalDays = int(currentTime.Sub(startDateTime).Hours()/24) + 1
|
||||
if totalDays <= 0 {
|
||||
totalDays = 1
|
||||
for d := startDateTime; !d.After(currentTime); d = d.AddDate(0, 0, 1) {
|
||||
dateList = append(dateList, d.Format("2006-01-02"))
|
||||
}
|
||||
}
|
||||
resultChan := make(chan models.MgUserDayRetention, totalDays)
|
||||
|
||||
// 按日期降序排列
|
||||
sort.Sort(sort.Reverse(sort.StringSlice(dateList)))
|
||||
|
||||
// 2. 计算总页数和总记录数
|
||||
totalCount := len(dateList)
|
||||
resp.Count = totalCount
|
||||
|
||||
// 3. 做分页裁剪
|
||||
startIdx := pageNum * req.PageSize
|
||||
endIdx := startIdx + req.PageSize
|
||||
if startIdx > totalCount {
|
||||
startIdx = totalCount
|
||||
}
|
||||
if endIdx > totalCount {
|
||||
endIdx = totalCount
|
||||
}
|
||||
pagedDates := dateList[startIdx:endIdx]
|
||||
|
||||
// 控制并发数的最大值,避免数据库过载
|
||||
sem := make(chan struct{}, 10) // 同时最多 10 个 goroutine 执行
|
||||
|
||||
// 根据 OnlyFirstDay 参数调整查询逻辑
|
||||
if req.OnlyFirstDay {
|
||||
// 如果只查询每个月1号的数据
|
||||
for {
|
||||
// 增加日期(开始日期自增一个月的1号)
|
||||
startDateTime, _ := time.Parse("2006-01-02", startDate)
|
||||
|
||||
// 如果当前日期大于等于startDate,且是查询下一个月的1号,则退出
|
||||
if startDateTime.After(time.Now()) {
|
||||
break
|
||||
}
|
||||
|
||||
resultChan := make(chan models.MgUserDayRetention, len(pagedDates))
|
||||
// 4. 遍历 pagedDates 查询留存数据
|
||||
for _, date := range pagedDates {
|
||||
wg.Add(1)
|
||||
sem <- struct{}{} // 占一个信号,表示有一个 goroutine 正在执行
|
||||
sem <- struct{}{}
|
||||
|
||||
go func(date string) {
|
||||
defer wg.Done()
|
||||
defer func() { <-sem }() // 释放一个信号,表示该 goroutine 执行完毕
|
||||
defer func() { <-sem }()
|
||||
|
||||
var retainedUserCount int64
|
||||
var unsubOnDay int64
|
||||
var localErr error // 使用局部变量
|
||||
var localErr error
|
||||
|
||||
// 查询该天的留存用户数
|
||||
localErr = e.Orm.Model(&models.MgOrder{}).
|
||||
Where("state = 1 AND created_at between ? and ?", currentMonthFirstDay, currentMonthNextFirstDay).
|
||||
Where("product_id = ?", req.SkuCode). // 添加SkuCode条件
|
||||
Where("channel_code = ?", req.Channel). // 添加Channel条件
|
||||
Or("state = 2 AND unsubscribe_time > ? AND created_at between ? and ? AND product_id = ? "+
|
||||
"and channel_code = ?", date+" 23:59:59",
|
||||
currentMonthFirstDay, currentMonthNextFirstDay, req.SkuCode, req.Channel).
|
||||
Where("product_id = ?", req.SkuCode).
|
||||
Where("channel_code = ?", req.Channel).
|
||||
Or("state = 2 AND unsubscribe_time > ? AND created_at between ? and ? AND product_id = ? and channel_code = ?",
|
||||
date+" 23:59:59", currentMonthFirstDay, currentMonthNextFirstDay, req.SkuCode, req.Channel).
|
||||
Count(&retainedUserCount).Error
|
||||
|
||||
// 查询该天的退订用户数
|
||||
localErr = e.Orm.Table("mg_order").
|
||||
Where("unsubscribe_time >= ?", date+" 00:00:00").
|
||||
Where("unsubscribe_time <= ?", date+" 23:59:59").
|
||||
Where("created_at >= ?", currentMonthFirstDay).
|
||||
Where("created_at < ?", currentMonthNextFirstDay).
|
||||
Where("state = 2"). // 状态为2表示退订
|
||||
Where("product_id = ?", req.SkuCode). // 添加SkuCode条件
|
||||
Where("channel_code = ?", req.Channel). // 添加Channel条件
|
||||
Where("state = 2").
|
||||
Where("product_id = ?", req.SkuCode).
|
||||
Where("channel_code = ?", req.Channel).
|
||||
Count(&unsubOnDay).Error
|
||||
|
||||
if localErr != nil {
|
||||
|
@ -1647,94 +1646,18 @@ func (e MiGuDeployService) UserDayRetentionList(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
// 留存率计算:如果新增用户数为0,留存率为0
|
||||
var retentionRate string
|
||||
retentionRate := "0.00%"
|
||||
if newUserCount > 0 {
|
||||
retentionRate = fmt.Sprintf("%.2f%%", float64(retainedUserCount)*100/float64(newUserCount))
|
||||
} else {
|
||||
retentionRate = "0.00%"
|
||||
}
|
||||
|
||||
// 将查询结果发送到 resultChan
|
||||
resultChan <- models.MgUserDayRetention{
|
||||
Date: date,
|
||||
RetainedUserCount: int(retainedUserCount),
|
||||
RetentionRate: retentionRate,
|
||||
UserUnsubOnDay: int(unsubOnDay),
|
||||
}
|
||||
}(startDate)
|
||||
|
||||
// 增加日期(开始日期自增一个月)
|
||||
startDate = startDateTime.AddDate(0, 1, 0).Format("2006-01-02")
|
||||
}
|
||||
} else {
|
||||
// 按天查询,直到留存数为 0 或查询到当前日期
|
||||
for {
|
||||
// 增加日期(开始日期自增一天)
|
||||
startDateTime, _ := time.Parse("2006-01-02", startDate)
|
||||
if startDate > currentDate {
|
||||
break
|
||||
}
|
||||
|
||||
wg.Add(1)
|
||||
sem <- struct{}{} // 占一个信号,表示有一个 goroutine 正在执行
|
||||
|
||||
go func(date string) {
|
||||
defer wg.Done()
|
||||
defer func() { <-sem }() // 释放一个信号,表示该 goroutine 执行完毕
|
||||
|
||||
var retainedUserCount int64
|
||||
var unsubOnDay int64
|
||||
var localErr error // 使用局部变量
|
||||
|
||||
// 查询该天的留存用户数
|
||||
err = e.Orm.Model(&models.MgOrder{}).
|
||||
Where("state = 1 AND created_at between ? and ?", currentMonthFirstDay, currentMonthNextFirstDay).
|
||||
Where("product_id = ?", req.SkuCode). // 添加SkuCode条件
|
||||
Where("channel_code = ?", req.Channel). // 添加Channel条件
|
||||
Or("state = 2 AND unsubscribe_time > ? AND created_at between ? and ? AND product_id = ? "+
|
||||
"and channel_code = ?", date+" 23:59:59",
|
||||
currentMonthFirstDay, currentMonthNextFirstDay, req.SkuCode, req.Channel).
|
||||
Count(&retainedUserCount).Error
|
||||
|
||||
//retainedUserCount, localErr = getRetentionForDay(date, e.Orm, currentMonthFirstDay, currentMonthNextFirstDay)
|
||||
|
||||
// 查询该天的退订用户数
|
||||
localErr = e.Orm.Table("mg_order").
|
||||
Where("unsubscribe_time >= ?", date+" 00:00:00").
|
||||
Where("unsubscribe_time <= ?", date+" 23:59:59").
|
||||
Where("created_at >= ?", currentMonthFirstDay).
|
||||
Where("created_at < ?", currentMonthNextFirstDay).
|
||||
Where("state = 2"). // 状态为2表示退订
|
||||
Where("product_id = ?", req.SkuCode). // 添加SkuCode条件
|
||||
Where("channel_code = ?", req.Channel). // 添加Channel条件
|
||||
Count(&unsubOnDay).Error
|
||||
|
||||
if localErr != nil {
|
||||
e.Logger.Error(localErr)
|
||||
return
|
||||
}
|
||||
|
||||
// 留存率计算:如果新增用户数为0,留存率为0
|
||||
var retentionRate string
|
||||
if newUserCount > 0 {
|
||||
retentionRate = fmt.Sprintf("%.2f%%", float64(retainedUserCount)*100/float64(newUserCount))
|
||||
} else {
|
||||
retentionRate = "0.00%"
|
||||
}
|
||||
|
||||
// 将查询结果发送到 resultChan
|
||||
resultChan <- models.MgUserDayRetention{
|
||||
Date: date,
|
||||
RetainedUserCount: int(retainedUserCount),
|
||||
RetentionRate: retentionRate,
|
||||
UserUnsubOnDay: int(unsubOnDay),
|
||||
}
|
||||
}(startDate)
|
||||
|
||||
// 增加日期(开始日期自增一天)
|
||||
startDate = startDateTime.AddDate(0, 0, 1).Format("2006-01-02")
|
||||
}
|
||||
}(date)
|
||||
}
|
||||
|
||||
// 等待所有 goroutine 执行完毕
|
||||
|
@ -1746,41 +1669,324 @@ func (e MiGuDeployService) UserDayRetentionList(c *gin.Context) {
|
|||
retentionData = append(retentionData, result)
|
||||
}
|
||||
|
||||
if len(retentionData) < req.PageSize {
|
||||
var addDayRetention models.MgUserDayRetention
|
||||
addDayRetention.Date = addData.Date
|
||||
addDayRetention.RetainedUserCount = addData.ValidUserCount
|
||||
addDayRetention.RetentionRate = addData.EffectiveRate
|
||||
addDayRetention.UserUnsubOnDay = int(addData.UnsubscribedToday)
|
||||
retentionData = append(retentionData, addDayRetention)
|
||||
}
|
||||
|
||||
// 排序(按日期升序)
|
||||
sort.SliceStable(retentionData, func(i, j int) bool {
|
||||
return retentionData[i].Date > retentionData[j].Date
|
||||
})
|
||||
|
||||
// 分页处理
|
||||
totalRecords := len(retentionData) // 总记录数
|
||||
startIdx := pageNum * req.PageSize
|
||||
endIdx := startIdx + req.PageSize
|
||||
|
||||
if startIdx > totalRecords {
|
||||
resp.List = []models.MgUserDayRetention{}
|
||||
resp.Count = totalRecords
|
||||
e.OK(resp, "success")
|
||||
return
|
||||
}
|
||||
|
||||
if endIdx > totalRecords {
|
||||
endIdx = totalRecords
|
||||
}
|
||||
|
||||
// 返回分页后的数据
|
||||
resp.List = retentionData[startIdx:endIdx]
|
||||
resp.List = retentionData
|
||||
resp.Count = totalRecords
|
||||
|
||||
e.OK(resp, "success")
|
||||
}
|
||||
|
||||
//func (e MiGuDeployService) UserDayRetentionList(c *gin.Context) {
|
||||
// // 创建上下文和 ORM
|
||||
// ctx := e.MakeContext(c)
|
||||
// if err := ctx.MakeOrm().Errors; err != nil {
|
||||
// e.Logger.Error(err)
|
||||
// response.Error(c, http.StatusInternalServerError, err, "数据库错误")
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// // 解析请求参数
|
||||
// req := &models.UserDayRetentionListReq{}
|
||||
// if err := c.ShouldBindJSON(req); err != nil {
|
||||
// response.Error(c, http.StatusBadRequest, err, "参数错误")
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// resp := models.UserDayRetentionListResp{
|
||||
// PageNum: req.PageNum,
|
||||
// }
|
||||
//
|
||||
// // 分页处理
|
||||
// pageNum := req.PageNum - 1
|
||||
// if pageNum < 0 {
|
||||
// pageNum = 0
|
||||
// }
|
||||
// if req.PageSize == 0 {
|
||||
// req.PageSize = 10
|
||||
// }
|
||||
// resp.PageSize = req.PageSize
|
||||
//
|
||||
// // 获取新增用户数(在RetentionMonth的所有用户)
|
||||
// var newUserCount int64
|
||||
// err := e.Orm.Table("mg_order").
|
||||
// Where("created_at >= ?", req.RetentionMonth+"-01 00:00:00").
|
||||
// Where("created_at < ?", req.RetentionMonth+"-31 23:59:59").
|
||||
// Where("product_id = ?", req.SkuCode). // 添加SkuCode条件
|
||||
// Where("channel_code = ?", req.Channel). // 添加Channel条件
|
||||
// Count(&newUserCount).Error
|
||||
// if err != nil {
|
||||
// e.Logger.Error(err)
|
||||
// response.Error(c, http.StatusInternalServerError, err, "获取新增用户数失败")
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// // 如果没有新增用户,则直接返回空结果
|
||||
// if newUserCount == 0 {
|
||||
// resp.List = []models.MgUserDayRetention{}
|
||||
// resp.Count = 0
|
||||
// e.OK(resp, "success")
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// addData, err := models.GetMonthlyEffectiveUserStats(e.Orm, req.RetentionMonth, req.SkuCode, req.Channel)
|
||||
// if err != nil {
|
||||
// e.Logger.Error(err)
|
||||
// response.Error(c, http.StatusInternalServerError, err, "获取当月留存数据失败")
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// // 计算下个月的1号(留存查询从下个月1号开始)
|
||||
// parsedMonth, err := time.Parse("2006-01", req.RetentionMonth)
|
||||
// if err != nil {
|
||||
// e.Logger.Error(err)
|
||||
// response.Error(c, http.StatusBadRequest, err, "解析RetentionMonth失败")
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// // 获取下个月的1号
|
||||
// nextMonth := parsedMonth.AddDate(0, 1, 0) // 加一个月
|
||||
// startDate := nextMonth.Format("2006-01-02") // 下个月1号
|
||||
//
|
||||
// // 获取当前日期,作为退出条件
|
||||
// currentDate := time.Now().Format("2006-01-02")
|
||||
//
|
||||
// // 获取当前记录的 RetentionMonth
|
||||
// year, month, _ := models.ParseYearMonth(req.RetentionMonth)
|
||||
//
|
||||
// // 计算当前月1号和上个月1号
|
||||
// currentMonthFirstDay := time.Date(year, month, 1, 0, 0, 0, 0, time.Local) // 统计月的1号
|
||||
// currentMonthNextFirstDay := time.Date(year, month+1, 1, 0, 0, 0, 0, time.Local) // 统计月的次月1号
|
||||
//
|
||||
// // 初始化结果列表
|
||||
// var retentionData []models.MgUserDayRetention
|
||||
//
|
||||
// // 使用 goroutine 处理并发查询
|
||||
// var wg sync.WaitGroup
|
||||
//
|
||||
// // 创建一个 channel 来接收每一天的查询结果
|
||||
// //resultChan := make(chan models.MgUserDayRetention, 100)
|
||||
//
|
||||
// // 计算预计查询天数(或月份)
|
||||
// var totalDays int
|
||||
// if req.OnlyFirstDay {
|
||||
// // 当前月的1号
|
||||
// now := time.Now()
|
||||
// currentMonthFirst := time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, now.Location())
|
||||
// // 计算从 nextMonth 到 currentMonthFirst 包含的1号数量
|
||||
// totalDays = countFirstDays(nextMonth, currentMonthFirst)
|
||||
// } else {
|
||||
// // 按天查询:计算两个日期之间的天数
|
||||
// startDateTime, _ := time.Parse("2006-01-02", startDate)
|
||||
// currentTime, _ := time.Parse("2006-01-02", currentDate)
|
||||
// totalDays = int(currentTime.Sub(startDateTime).Hours()/24) + 1
|
||||
// if totalDays <= 0 {
|
||||
// totalDays = 1
|
||||
// }
|
||||
// }
|
||||
// resultChan := make(chan models.MgUserDayRetention, totalDays)
|
||||
//
|
||||
// // 控制并发数的最大值,避免数据库过载
|
||||
// sem := make(chan struct{}, 10) // 同时最多 10 个 goroutine 执行
|
||||
//
|
||||
// // 根据 OnlyFirstDay 参数调整查询逻辑
|
||||
// if req.OnlyFirstDay {
|
||||
// // 如果只查询每个月1号的数据
|
||||
// for {
|
||||
// // 增加日期(开始日期自增一个月的1号)
|
||||
// startDateTime, _ := time.Parse("2006-01-02", startDate)
|
||||
//
|
||||
// // 如果当前日期大于等于startDate,且是查询下一个月的1号,则退出
|
||||
// if startDateTime.After(time.Now()) {
|
||||
// break
|
||||
// }
|
||||
//
|
||||
// wg.Add(1)
|
||||
// sem <- struct{}{} // 占一个信号,表示有一个 goroutine 正在执行
|
||||
//
|
||||
// go func(date string) {
|
||||
// defer wg.Done()
|
||||
// defer func() { <-sem }() // 释放一个信号,表示该 goroutine 执行完毕
|
||||
//
|
||||
// var retainedUserCount int64
|
||||
// var unsubOnDay int64
|
||||
// var localErr error // 使用局部变量
|
||||
//
|
||||
// // 查询该天的留存用户数
|
||||
// localErr = e.Orm.Model(&models.MgOrder{}).
|
||||
// Where("state = 1 AND created_at between ? and ?", currentMonthFirstDay, currentMonthNextFirstDay).
|
||||
// Where("product_id = ?", req.SkuCode). // 添加SkuCode条件
|
||||
// Where("channel_code = ?", req.Channel). // 添加Channel条件
|
||||
// Or("state = 2 AND unsubscribe_time > ? AND created_at between ? and ? AND product_id = ? "+
|
||||
// "and channel_code = ?", date+" 23:59:59",
|
||||
// currentMonthFirstDay, currentMonthNextFirstDay, req.SkuCode, req.Channel).
|
||||
// Count(&retainedUserCount).Error
|
||||
//
|
||||
// // 查询该天的退订用户数
|
||||
// localErr = e.Orm.Table("mg_order").
|
||||
// Where("unsubscribe_time >= ?", date+" 00:00:00").
|
||||
// Where("unsubscribe_time <= ?", date+" 23:59:59").
|
||||
// Where("created_at >= ?", currentMonthFirstDay).
|
||||
// Where("created_at < ?", currentMonthNextFirstDay).
|
||||
// Where("state = 2"). // 状态为2表示退订
|
||||
// Where("product_id = ?", req.SkuCode). // 添加SkuCode条件
|
||||
// Where("channel_code = ?", req.Channel). // 添加Channel条件
|
||||
// Count(&unsubOnDay).Error
|
||||
//
|
||||
// if localErr != nil {
|
||||
// e.Logger.Error(localErr)
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// // 留存率计算:如果新增用户数为0,留存率为0
|
||||
// var retentionRate string
|
||||
// if newUserCount > 0 {
|
||||
// retentionRate = fmt.Sprintf("%.2f%%", float64(retainedUserCount)*100/float64(newUserCount))
|
||||
// } else {
|
||||
// retentionRate = "0.00%"
|
||||
// }
|
||||
//
|
||||
// // 将查询结果发送到 resultChan
|
||||
// resultChan <- models.MgUserDayRetention{
|
||||
// Date: date,
|
||||
// RetainedUserCount: int(retainedUserCount),
|
||||
// RetentionRate: retentionRate,
|
||||
// UserUnsubOnDay: int(unsubOnDay),
|
||||
// }
|
||||
// }(startDate)
|
||||
//
|
||||
// // 增加日期(开始日期自增一个月)
|
||||
// startDate = startDateTime.AddDate(0, 1, 0).Format("2006-01-02")
|
||||
// }
|
||||
// } else {
|
||||
// // 按天查询,直到留存数为 0 或查询到当前日期
|
||||
// for {
|
||||
// // 增加日期(开始日期自增一天)
|
||||
// startDateTime, _ := time.Parse("2006-01-02", startDate)
|
||||
// if startDate > currentDate {
|
||||
// break
|
||||
// }
|
||||
//
|
||||
// wg.Add(1)
|
||||
// sem <- struct{}{} // 占一个信号,表示有一个 goroutine 正在执行
|
||||
//
|
||||
// go func(date string) {
|
||||
// defer wg.Done()
|
||||
// defer func() { <-sem }() // 释放一个信号,表示该 goroutine 执行完毕
|
||||
//
|
||||
// var retainedUserCount int64
|
||||
// var unsubOnDay int64
|
||||
// var localErr error // 使用局部变量
|
||||
//
|
||||
// // 查询该天的留存用户数
|
||||
// err = e.Orm.Model(&models.MgOrder{}).
|
||||
// Where("state = 1 AND created_at between ? and ?", currentMonthFirstDay, currentMonthNextFirstDay).
|
||||
// Where("product_id = ?", req.SkuCode). // 添加SkuCode条件
|
||||
// Where("channel_code = ?", req.Channel). // 添加Channel条件
|
||||
// Or("state = 2 AND unsubscribe_time > ? AND created_at between ? and ? AND product_id = ? "+
|
||||
// "and channel_code = ?", date+" 23:59:59",
|
||||
// currentMonthFirstDay, currentMonthNextFirstDay, req.SkuCode, req.Channel).
|
||||
// Count(&retainedUserCount).Error
|
||||
//
|
||||
// //retainedUserCount, localErr = getRetentionForDay(date, e.Orm, currentMonthFirstDay, currentMonthNextFirstDay)
|
||||
//
|
||||
// // 查询该天的退订用户数
|
||||
// localErr = e.Orm.Table("mg_order").
|
||||
// Where("unsubscribe_time >= ?", date+" 00:00:00").
|
||||
// Where("unsubscribe_time <= ?", date+" 23:59:59").
|
||||
// Where("created_at >= ?", currentMonthFirstDay).
|
||||
// Where("created_at < ?", currentMonthNextFirstDay).
|
||||
// Where("state = 2"). // 状态为2表示退订
|
||||
// Where("product_id = ?", req.SkuCode). // 添加SkuCode条件
|
||||
// Where("channel_code = ?", req.Channel). // 添加Channel条件
|
||||
// Count(&unsubOnDay).Error
|
||||
//
|
||||
// if localErr != nil {
|
||||
// e.Logger.Error(localErr)
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// // 留存率计算:如果新增用户数为0,留存率为0
|
||||
// var retentionRate string
|
||||
// if newUserCount > 0 {
|
||||
// retentionRate = fmt.Sprintf("%.2f%%", float64(retainedUserCount)*100/float64(newUserCount))
|
||||
// } else {
|
||||
// retentionRate = "0.00%"
|
||||
// }
|
||||
//
|
||||
// // 将查询结果发送到 resultChan
|
||||
// resultChan <- models.MgUserDayRetention{
|
||||
// Date: date,
|
||||
// RetainedUserCount: int(retainedUserCount),
|
||||
// RetentionRate: retentionRate,
|
||||
// UserUnsubOnDay: int(unsubOnDay),
|
||||
// }
|
||||
// }(startDate)
|
||||
//
|
||||
// // 增加日期(开始日期自增一天)
|
||||
// startDate = startDateTime.AddDate(0, 0, 1).Format("2006-01-02")
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // 等待所有 goroutine 执行完毕
|
||||
// wg.Wait()
|
||||
// close(resultChan)
|
||||
//
|
||||
// // 从 channel 中获取所有查询结果,并汇总
|
||||
// for result := range resultChan {
|
||||
// retentionData = append(retentionData, result)
|
||||
// }
|
||||
//
|
||||
// var addDayRetention models.MgUserDayRetention
|
||||
// addDayRetention.Date = addData.Date
|
||||
// addDayRetention.RetainedUserCount = addData.ValidUserCount
|
||||
// addDayRetention.RetentionRate = addData.EffectiveRate
|
||||
// addDayRetention.UserUnsubOnDay = int(addData.UnsubscribedToday)
|
||||
// retentionData = append(retentionData, addDayRetention)
|
||||
//
|
||||
// // 排序(按日期升序)
|
||||
// sort.SliceStable(retentionData, func(i, j int) bool {
|
||||
// return retentionData[i].Date > retentionData[j].Date
|
||||
// })
|
||||
//
|
||||
// // 分页处理
|
||||
// totalRecords := len(retentionData) // 总记录数
|
||||
// startIdx := pageNum * req.PageSize
|
||||
// endIdx := startIdx + req.PageSize
|
||||
//
|
||||
// if startIdx > totalRecords {
|
||||
// resp.List = []models.MgUserDayRetention{}
|
||||
// resp.Count = totalRecords
|
||||
// e.OK(resp, "success")
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// if endIdx > totalRecords {
|
||||
// endIdx = totalRecords
|
||||
// }
|
||||
//
|
||||
// // 返回分页后的数据
|
||||
// resp.List = retentionData[startIdx:endIdx]
|
||||
// resp.Count = totalRecords
|
||||
//
|
||||
// e.OK(resp, "success")
|
||||
//}
|
||||
|
||||
// monthsBetween 返回 start 和 end 之间完整的月份数。
|
||||
// 如果 end 的日期在 start 的日期之前(不满一个月),则不计入。
|
||||
func monthsBetween(start, end time.Time) int {
|
||||
|
|
Loading…
Reference in New Issue
Block a user