You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

332 lines
9.5 KiB
Go

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package campaignstat
import (
"joybuywork/internal/consts"
"joybuywork/internal/repository/cache"
"joybuywork/internal/repository/finder"
"joybuywork/internal/repository/model"
"joybuywork/internal/repository/mtype"
"joybuywork/internal/service/provider"
"joybuywork/internal/utils"
"joybuywork/internal/utils/logic"
pb "joybuywork/proto/go_proto/w_campaign_stat"
"joybuywork/proto/go_proto/workerr"
"fmt"
"github.com/golang-module/carbon/v2"
)
// 展示类型(1-活动访问,2-达标条件,3-签到)
const (
statCampaignShowTypeVisit = iota + 1
statCampaignShowTypeCond
statCampaignShowTypeSign
statCampaignShowTypeGrow
)
type Campaign struct {
logic.Logic
Req *pb.CampaignReq
Res *pb.CampaignRes
conf *model.FissionCampaignConfig
}
func (s *Campaign) Run() error {
return logic.Run(s)
}
func (s *Campaign) Exec() (err error) {
cpn, err := s.campaign()
if err != nil {
return
}
start, end, statType := s.statParams(cpn)
err = s.line(cpn, start, end, statType)
if err != nil {
return
}
err = s.change(cpn, start, end)
if err != nil {
return
}
return
}
// 活动数据
func (s *Campaign) campaign() (cpn *model.FissionCampaign, err error) {
cpn, err = finder.Campaign(s.Ctx, s.Req.GetCampaignHashId())
if err != nil {
err = s.BE().CacheError(err)
return
}
if cpn == nil || cpn.IsDel == mtype.Yes {
return nil, workerr.NotFound("campaign not found")
}
return
}
// 统计参数
func (s *Campaign) statParams(cpn *model.FissionCampaign) (start, end carbon.Carbon, statType int8) {
start = utils.Ternary(s.Req.GetStartTime() != 0, carbon.CreateFromTimestamp(s.Req.GetStartTime()), carbon.Now().StartOfDay())
end = utils.Ternary(s.Req.GetEndTime() != 0, carbon.CreateFromTimestamp(s.Req.GetEndTime()), carbon.Now())
statType = mtype.FissionTotalCycleTypeHour
if start.AddDay().Lt(end) {
statType = mtype.FissionTotalCycleTypeDay
}
// 自定义事件的统计标识
conf, err := cache.NewCampaignConfig(s.Ctx).FindByCampaignId(cpn.ID)
if err != nil {
err = s.BE().CacheError(err)
return
}
s.conf = conf
switch cpn.FissionID {
case consts.IdSignIn:
s.Res.ShowType = statCampaignShowTypeSign
case consts.IdGrow:
s.Res.ShowType = statCampaignShowTypeGrow
default:
s.Res.ShowType = utils.Ternary[int32](conf.Option == mtype.FissionCampaignConfigTargetOptionApp, statCampaignShowTypeVisit, statCampaignShowTypeCond)
}
s.Res.ReportUser = &pb.CampaignRes_Report{}
s.Res.ReportNum = &pb.CampaignRes_Report{}
return
}
// 线数据
func (s *Campaign) line(cpn *model.FissionCampaign, start, end carbon.Carbon, statType int8) (err error) {
marks, markName, err := s.lineMark(cpn)
if err != nil {
return
}
m := s.GetDao().FissionTotalCycle
list, err := m.WithContext(s.Ctx).
Where(
m.StatTime.Gte(start.Timestamp()),
m.StatTime.Lte(end.Timestamp()),
m.CampaignID.Eq(cpn.ID),
m.StatType.Eq(statType),
m.Mark.In(marks...),
).Find()
var x []string
var xMap = make(map[string]int)
switch statType {
case mtype.FissionTotalCycleTypeHour:
hours := utils.BetweenHour(start, end)
x = make([]string, 0, len(hours))
for k, v := range hours {
key := fmt.Sprintf("%dh", v)
x = append(x, key)
xMap[key] = k
}
case mtype.FissionTotalCycleTypeDay:
x = utils.BetweenDay(start, end)
for k, v := range x {
xMap[v] = k
}
}
//人数
xLen := len(x)
var nf, unf = "num", "user_num"
var lineMap = make(map[string]map[string]*pb.CampaignRes_Y)
for _, mark := range marks {
t := utils.BehaviorMarkToType(mark)
lineMap[mark] = map[string]*pb.CampaignRes_Y{
nf: {
Type: t,
Name: markName[mark],
Data: make([]int64, xLen),
},
unf: {
Type: t,
Name: markName[mark],
Data: make([]int64, xLen),
},
}
}
for _, v := range list {
var idx int
var t = carbon.CreateFromTimestamp(v.StatTime)
switch statType {
case mtype.FissionTotalCycleTypeHour:
idx = xMap[fmt.Sprintf("%dh", t.Hour())]
case mtype.FissionTotalCycleTypeDay:
idx = xMap[t.ToShortDateString()]
}
lineMap[v.Mark][nf].Data[idx] = v.Num
lineMap[v.Mark][unf].Data[idx] = v.UserNum
}
// 即时数据
pTotal := provider.NewFissionBehaviorTotal(s.Ctx, cpn.ID)
var immNum, immUserNum map[string]int64
var immIdx int
now := carbon.Now()
switch statType {
case mtype.FissionTotalCycleTypeHour:
if now.StartOfDay().Eq(start.StartOfDay()) { // 当天的某一个小时
immIdx = xMap[fmt.Sprintf("%dh", now.Hour())]
immNum, immUserNum, err = pTotal.CycleHour(now, marks...)
if err != nil {
return
}
}
case mtype.FissionTotalCycleTypeDay:
if end.Gte(now) { // 如果结束时间大于当前时间
dayStr := now.ToShortDateString()
immIdx = xMap[dayStr]
immNum, immUserNum, err = pTotal.CycleDay(now, marks...)
if err != nil {
return
}
}
}
for k, v := range immNum {
lineMap[k][nf].Data[immIdx] = v
}
for k, v := range immUserNum {
lineMap[k][unf].Data[immIdx] = v
}
s.AddAfterRun(func() (err error) {
s.Res.X = x
for _, v := range marks {
s.Res.ReportNum.Y = append(s.Res.ReportNum.Y, lineMap[v][nf])
s.Res.ReportUser.Y = append(s.Res.ReportUser.Y, lineMap[v][unf])
}
return
})
return
}
func (s *Campaign) lineMark(cpn *model.FissionCampaign) (marks []string, markName map[string]string, err error) {
switch cpn.FissionID {
case consts.IdSignIn:
marks = []string{
mtype.FissionBehaviorMarkSign,
mtype.FissionBehaviorMarkSignTarget,
}
return
case consts.IdGrow:
marks = []string{
mtype.FissionBehaviorMarkView,
mtype.FissionBehaviorMarkGrow,
}
return
}
marks = []string{
mtype.FissionBehaviorMarkView,
mtype.FissionBehaviorMarkClickShare,
}
if s.conf.Option == mtype.FissionCampaignConfigTargetOptionApp && s.conf.AppEvent == mtype.FissionCampaignConfigTargetAppEventRegister {
marks = append(marks, mtype.FissionBehaviorMarkAppRegister)
} else {
marks = append(marks, mtype.FissionBehaviorMarkAppInstall)
}
markName = make(map[string]string)
if s.conf.Option != mtype.FissionCampaignConfigTargetOptionApp {
condM := s.GetDao().FissionCampaignCond
var conds []*model.FissionCampaignCond
conds, err = condM.WithContext(s.Ctx).Where(condM.CampaignID.Eq(cpn.ID)).
Where(
condM.WithContext(s.Ctx).
Or(condM.IsDel.Eq(mtype.No)).
Or(condM.IsDel.Eq(mtype.Yes), condM.DelUse.Eq(mtype.Yes)),
).Find()
if err != nil {
err = s.BE().MysqlError(err)
return
}
for _, cond := range conds {
mark := utils.BehaviorFormatMark(mtype.FissionBehaviorTypeFinishCond, cond.ID)
marks = append(marks, mark)
markName[mark] = cond.Event
}
marks = append(marks, mtype.FissionBehaviorMarkFinishTask)
}
return
}
func (s *Campaign) change(cpn *model.FissionCampaign, start, end carbon.Carbon) (err error) {
total := provider.NewFissionBehaviorTotal(s.Ctx, cpn.ID)
var (
viewUser = total.UserNumType(mtype.FissionBehaviorTypeView, start, end) //活动页面访问人数
viewNum = total.NumType(mtype.FissionBehaviorTypeView, start, end) //活动页面访问次数
clickPlayUser = total.UserNumType(mtype.FissionBehaviorTypeClickPlay, start, end) //活动按钮点击人数
clickPlayNum = total.NumType(mtype.FissionBehaviorTypeClickPlay, start, end) //活动按钮点击次数
clickShareUser = total.UserNumType(mtype.FissionBehaviorTypeClickShare, start, end) //活动分享按钮点击人数
clickShareNum = total.NumType(mtype.FissionBehaviorTypeClickShare, start, end) //活动分享按钮点击次数
clickMediaUser = total.UserNumType(mtype.FissionBehaviorTypeClickMedia, start, end) //活动社媒点击人数
clickMediaNum = total.NumType(mtype.FissionBehaviorTypeClickMedia, start, end) //活动社媒点击次数
finishTaskUser = total.UserNumType(mtype.FissionBehaviorTypeFinishTask, start, end) //活动完成目标人数
finishTaskNum = total.NumType(mtype.FissionBehaviorTypeFinishTask, start, end) //活动完成目标次数
signUser = total.UserNumType(mtype.FissionBehaviorTypeSign, start, end) //活动签到人数
signNum = total.NumType(mtype.FissionBehaviorTypeSign, start, end) //活动签到次数
signTargetUser = total.UserNumType(mtype.FissionBehaviorTypeSignTarget, start, end) //活动签到达标人数
signTargetNum = total.NumType(mtype.FissionBehaviorTypeSignTarget, start, end) //活动签到达标次数
growOkUser = total.UserNumType(mtype.FissionBehaviorTypeGrow, start, end) //领养人数
growOkNum = total.NumType(mtype.FissionBehaviorTypeGrow, start, end) //领养次数
)
s.AddAfterRun(func() (err error) {
s.Res.ReportNum.TargetNum = finishTaskNum
s.Res.ReportUser.TargetNum = finishTaskUser
s.Res.ReportNum.ViewNum = viewNum
s.Res.ReportUser.ViewNum = viewUser
s.Res.ReportNum.SignNum = signNum
s.Res.ReportUser.SignNum = signUser
s.Res.ReportNum.Change = utils.PercentNoZero(clickShareNum+clickMediaNum, viewNum)
s.Res.ReportUser.Change = utils.PercentNoZero(clickShareUser+clickMediaUser, viewUser)
s.Res.ReportNum.Fun = utils.PercentNoZero(clickPlayNum, viewNum)
s.Res.ReportUser.Fun = utils.PercentNoZero(clickPlayUser, viewUser)
s.Res.ReportNum.Target = utils.PercentNoZero(finishTaskNum, viewNum)
s.Res.ReportUser.Target = utils.PercentNoZero(finishTaskUser, viewUser)
s.Res.ReportNum.Sign = utils.PercentNoZero(signTargetNum, signNum)
s.Res.ReportUser.Sign = utils.PercentNoZero(signTargetUser, signUser)
s.Res.ReportNum.Grow = utils.PercentNoZero(growOkNum, viewNum)
s.Res.ReportUser.Grow = utils.PercentNoZero(growOkUser, viewUser)
return
})
return
}