package service import ( "joybuywork/internal/app" "joybuywork/internal/consts/ckey" "joybuywork/internal/repository/cache" "joybuywork/internal/repository/dbcheck" "joybuywork/internal/repository/finder" "joybuywork/internal/repository/model" "joybuywork/internal/repository/mtype" "joybuywork/internal/repository/withdefault" "joybuywork/internal/service/cmm" containers "joybuywork/internal/service/containers/campaignstat" "joybuywork/internal/service/provider/fissionaction" "joybuywork/internal/utils" "joybuywork/internal/utils/blink" "joybuywork/internal/utils/verify" pb "joybuywork/proto/go_proto/w_campaign_stat" "joybuywork/proto/go_proto/workerr" "time" bi_fission_actionpb "gits.branchcn.com/backend/fissionbi/proto/go_proto/bi_fission_action" ) type WCampaignStat struct { Service } // Summary 活动概览数据 func (s *WCampaignStat) Summary(req *pb.SummaryReq, res *pb.SummaryRes) (err error) { defer s.checkErr() *res = pb.SummaryRes{} container := new(containers.Summary) { container.Init(s.ctx) container.Req = req container.Res = res } return container.Run() } // Campaign 活动数据 func (s *WCampaignStat) Campaign(req *pb.CampaignReq, res *pb.CampaignRes) (err error) { defer s.checkErr() *res = pb.CampaignRes{} container := new(containers.Campaign) { container.Init(s.ctx) container.Req = req container.Res = res } return container.Run() } // Related 裂变数据 func (s *WCampaignStat) Related(req *pb.RelatedReq, res *pb.RelatedRes) (err error) { defer s.checkErr() *res = pb.RelatedRes{} container := new(containers.Related) { container.Init(s.ctx) container.Req = req container.Res = res } return container.Run() } // Stat 统计事件数据 func (s *WCampaignStat) Stat(req *pb.StatReq, res *pb.StatRes) (err error) { defer s.checkErr() *res = pb.StatRes{} container := new(containers.Stat) { container.Init(s.ctx) container.Req = req container.Res = res } return container.Run() } // Channel 渠道统计 func (s *WCampaignStat) Channel(req *pb.ChannelReq, res *pb.ChannelRes) (err error) { defer s.checkErr() cpn, err := finder.Campaign(s.ctx, req.GetCampaignHashId()) if err != nil { return s.BE().CacheError(err) } if cpn == nil { return } m := s.GetDao().FissionCampaignChannel offset, limit := utils.PpDbLo(req.GetPage(), req.GetPerPage()) list, total, err := m.WithContext(s.ctx).Where( m.CampaignID.Eq(cpn.ID), m.CType.Eq(int8(req.GetCType())), m.IsDel.Eq(mtype.No), ).Order(m.ID).FindByPage(offset, limit) if err != nil { return s.BE().MysqlError(err) } if total == 0 { return } var totalMark = []int32{ mtype.FissionActionTypeAppInstall, mtype.FissionActionTypeWebFirstOpen, mtype.FissionActionTypeAppOpen, } switch req.GetCType() { case mtype.FissionCampaignChannelTypeApp: totalMark = append(totalMark, mtype.FissionActionTypeView) case mtype.FissionCampaignChannelTypeWeb: totalMark = append(totalMark, mtype.FissionActionTypeViewWeb) } var clickNum, clickUser = make(map[int64]int64), make(map[int64]int64) var installNum, installUser = make(map[int64]int64), make(map[int64]int64) var openNum, openUser = make(map[int64]int64), make(map[int64]int64) for _, tm := range totalMark { channelTotal, _ := app.NewFissionBiFissionAction().ChannelTotal(s.ctx, &bi_fission_actionpb.ChannelTotalReq{ CampaignId: cpn.ID, Type: tm, Tz: 8, Start: req.GetStartTime(), End: req.GetEndTime(), }) for _, v := range channelTotal.GetList() { switch tm { case mtype.FissionActionTypeAppInstall, mtype.FissionActionTypeWebFirstOpen: installNum[v.GetChannelId()] += v.GetNum() installUser[v.GetChannelId()] += v.GetUserNum() case mtype.FissionActionTypeAppOpen: openNum[v.GetChannelId()] += v.GetNum() openUser[v.GetChannelId()] += v.GetUserNum() case mtype.FissionActionTypeView, mtype.FissionActionTypeViewWeb: clickNum[v.GetChannelId()] += v.GetNum() clickUser[v.GetChannelId()] += v.GetUserNum() } } } *res = pb.ChannelRes{ List: make([]*pb.ChannelRes_One, 0, len(list)), Total: total, } project, err := finder.Project(s.ctx, cpn.ProjectID) if err != nil { return s.BE().CacheError(err) } if project == nil || project.IsDel == mtype.Yes { return workerr.NotFound("not found project") } for _, v := range list { one := &pb.ChannelRes_One{ Id: v.ID, Title: v.Title, Url: "", ClickNum: clickNum[v.ID], ClickUserNum: clickUser[v.ID], InstallNum: installNum[v.ID], InstallUserNum: installUser[v.ID], OpenNum: openNum[v.ID], OpenUserNum: openUser[v.ID], } switch v.CType { case mtype.FissionCampaignChannelTypeApp: one.Url = blink.NewCampaignLink(project.Domain, cpn.HashID, v.Mark).CampaignShareLink() case mtype.FissionCampaignChannelTypeWeb: one.Url = blink.NewCampaignLink(project.Domain, cpn.HashID, v.Mark).CampaignWebLink() } res.List = append(res.List, one) } return } // AdsSummary Ads总揽数据 func (s *WCampaignStat) AdsSummary(req *pb.AdsSummaryReq, res *pb.AdsSummaryRes) (err error) { defer s.checkErr() *res = pb.AdsSummaryRes{} container := new(containers.AdsSummary) { container.Init(s.ctx) container.Req = req container.Res = res } return container.Run() } // AdsTable Ads报表 func (s *WCampaignStat) AdsTable(req *pb.AdsTableReq, res *pb.AdsTableRes) (err error) { defer s.checkErr() *res = pb.AdsTableRes{} container := new(containers.AdsTable) { container.Init(s.ctx) container.Req = req container.Res = res } return container.Run() } // AdsReward Ads奖品 func (s *WCampaignStat) AdsReward(req *pb.AdsRewardReq, res *pb.AdsRewardRes) (err error) { defer s.checkErr() *res = pb.AdsRewardRes{} container := new(containers.AdsReward) { container.Init(s.ctx) container.Req = req container.Res = res } return container.Run() } // InAppBP 应用内埋点 func (s *WCampaignStat) InAppBP(req *pb.InAppBPReq, res *pb.InAppBPRes) (err error) { defer s.checkErr() cpn, err := cache.NewCampaign(s.ctx).FindById(req.GetCampaiginId()) if err != nil { err = s.BE().CacheError(err) return } if cpn == nil || !verify.InArray(cpn.Status, mtype.FissionCampaignStatusPub, mtype.FissionCampaignStatusPubPre) || cpn.ReportType != mtype.FissionCampaignReportTypeNew { return } user, err := cache.NewFissionUser(s.ctx, cpn.ID).FindById(req.GetUserId()) if err != nil { err = s.BE().CacheError(err) return } if user == nil || user.IsView == mtype.Yes { return } bp := fissionaction.NewMarkPoint(s.ctx).InApp(user) //支持埋点类型(5-活动按钮点击,6-点击分享按钮,10-点击去完成,18-点击去使用,19-长图点击, //21-我的任务弹窗,22-我的奖励记录弹窗,23-规则,24-展示表单,25-复制联系方式,29-展示弹窗,31-回答题目,37-点击立即翻牌,40-点击自定义按钮,53-进入ai对话) switch req.GetType() { case mtype.FissionActionTypeClickPlay: bp.ClickPlay(time.Now().Unix(), req.GetIp(), req.GetFrom()) case mtype.FissionActionTypeClickShare: bp.ClickShare(time.Now().Unix(), req.GetMediaId(), req.GetIp()) case mtype.FissionActionTypeToUse: bp.ToUse(time.Now().Unix(), req.GetRewardId(), req.GetIp(), req.GetFrom()) case mtype.FissionActionTypeClickCond: bp.ClickCond(time.Now().Unix(), req.GetCondId(), req.GetIp(), req.GetFrom()) case mtype.FissionActionTypeClickLongImg: bp.ClickLongImg(time.Now().Unix(), req.GetImgUrl(), req.GetImgId(), req.GetZoneId(), req.GetIp()) case mtype.FissionActionTypeClickMyTask: bp.ClickMyTask(time.Now().Unix(), req.GetIp()) case mtype.FissionActionTypeClickMyReward: bp.ClickMyReward(time.Now().Unix(), req.GetIp()) case mtype.FissionActionTypeClickRule: bp.ClickRule(time.Now().Unix(), req.GetIp()) case mtype.FissionActionTypeFormShow: bp.FormShow(time.Now().Unix(), req.GetFormShowStatus(), req.GetFrom(), req.GetRewardId(), req.GetRewardRecordId()) case mtype.FissionActionTypeCopyContact: bp.CopyContact(time.Now().Unix(), req.GetFrom(), req.GetRewardId()) case mtype.FissionActionTypeShowWindow: bp.ShowWindow(time.Now().Unix(), req.GetFrom()) case mtype.FissionActionTypeAnswerQa: bp.AnswerQa(time.Now().Unix(), req.GetQaId(), req.GetQaOptionId(), req.GetIsRight()) case mtype.FissionActionTypeClickFlip: bp.ClickFlip(time.Now().Unix(), req.GetClickFlipStatus()) case mtype.FissionActionTypeClickCustomBtn: bp.ClickCustomBtn(time.Now().Unix(), req.GetCustomBtnId()) case mtype.FissionActionTypeClickChat: bp.ClickChat(time.Now().Unix(), req.GetChatFrom(), req.GetChatTipMsg()) case mtype.FissionActionTypeClickUnoCard: bp.ClickUnoCard(time.Now().Unix(), req.GetColorMark(), req.GetCardNo(), req.GetUnoCardId()) default: } *res = pb.InAppBPRes{} return } // OutAppBP 应用外埋点 func (s *WCampaignStat) OutAppBP(req *pb.OutAppBPReq, res *pb.OutAppBPRes) (err error) { defer s.checkErr() cpn, err := cache.NewCampaign(s.ctx).FindByHashId(req.GetCampaignHashId()) if err != nil { err = s.BE().CacheError(err) return } if cpn == nil || !verify.InArray(cpn.Status, mtype.FissionCampaignStatusPub, mtype.FissionCampaignStatusPubPre) || cpn.ReportType != mtype.FissionCampaignReportTypeNew { return } channel, err := cmm.NewCMM(s.ctx, s.GetDao()).UserBindChannel(cpn.ID, req.GetCid()) if err != nil { return } var parentId int64 if req.GetParentUserId() != "" { parent, err1 := cache.NewFissionUser(s.ctx, cpn.ID).FindBySubUserId(req.GetParentUserId()) if err1 != nil { err = s.BE().CacheError(err1) return } if parent != nil { parentId = parent.ID } } bp := fissionaction.NewMarkPoint(s.ctx).OutApp(cpn.ID, channel.ID, parentId, req.GetWebId(), req.GetPlatform(), req.GetLang()) //埋点类型(1-访问活动,12-访问站外链接,13-活动按钮点击,7-浏览下载页行为, 8-点击下载按钮,9-浏览微信页行为,27-站内活动链接点击行为,51点击分享连接) switch req.GetType() { case mtype.FissionActionTypeView: bp.View(time.Now().Unix(), req.GetIp(), req.GetOs(), req.GetOsVersion(), req.GetDeviceModel()) case mtype.FissionActionTypeViewWeb: bp.ViewWeb(time.Now().Unix(), req.GetIp(), req.GetOs(), req.GetOsVersion(), req.GetDeviceModel()) case mtype.FissionActionTypeClickPlayWeb: bp.ClickPlayWeb(time.Now().Unix(), 0) case mtype.FissionActionTypeViewDownload: bp.ViewDownload(time.Now().Unix(), req.GetDownloadFrom(), req.GetIp(), req.GetOs(), req.GetOsVersion(), req.GetDeviceModel()) case mtype.FissionActionTypeClickDownload: bp.ClickDownload(time.Now().Unix(), req.GetDownloadFrom()) case mtype.FissionActionTypeViewWechat: bp.ViewWechat(time.Now().Unix(), req.GetIp()) case mtype.FissionActionTypeInAppOpenLink: bp.InAppOpenLink(time.Now().Unix(), req.GetBlackbox(), req.GetUid()) case mtype.FissionActionTypeClickShareLink: if parentId > 0 { bp.ClickShareLink(time.Now().Unix(), req.GetIp(), req.GetOs(), req.GetOsVersion(), req.GetDeviceModel()) } default: } *res = pb.OutAppBPRes{} return } // ReportInfo 报表信息 func (s *WCampaignStat) ReportInfo(req *pb.ReportInfoReq, res *pb.ReportInfoRes) (err error) { defer s.checkErr() *res = pb.ReportInfoRes{} container := new(containers.ReportInfo) { container.Init(s.ctx) container.Req = req container.Res = res } return container.Run() } // StatEvent 活动统计的维度 func (s *WCampaignStat) StatEvent(req *pb.StatEventReq, res *pb.StatEventRes) (err error) { defer s.checkErr() container := new(containers.StatEvent) { container.Init(s.ctx) container.Req = req container.Res = res } return container.Run() } // DemTitle 维度标题数据 func (s *WCampaignStat) DemTitle(req *pb.DemTitleReq, res *pb.DemTitleRes) (err error) { defer s.checkErr() *res = pb.DemTitleRes{} container := new(containers.DemTitle) { container.Init(s.ctx) container.Req = req container.Res = res } return container.Run() } // TopTen 活动前十排行榜 func (s *WCampaignStat) TopTen(req *pb.TopTenReq, res *pb.TopTenRes) (err error) { defer s.checkErr() *res = pb.TopTenRes{} container := new(containers.TopTen) { container.Init(s.ctx) container.Req = req container.Res = res } return container.Run() } // UserCycle 用户明细占比数据 func (s *WCampaignStat) UserCycle(req *pb.UserCycleReq, res *pb.UserCycleRes) (err error) { defer s.checkErr() *res = pb.UserCycleRes{} container := new(containers.UserCycle) { container.Init(s.ctx) container.Req = req container.Res = res } return container.Run() } // Active 用户活跃 func (s *WCampaignStat) Active(req *pb.ActiveReq, res *pb.ActiveRes) (err error) { defer s.checkErr() if !app.NewRedisLock(s.ctx, ckey.FissionStatActiveOnce(req.GetUserId())).SoftLock() { return } m := s.GetDao().FissionUserActive info, err := m.WithContext(s.ctx).Where(m.UserID.Eq(req.GetUserId()), m.CampaignID.Eq(req.GetCampaignId())).Take() if err = dbcheck.DbError(err); err != nil { err = s.BE().MysqlError(err) return } if info == nil { err = m.WithContext(s.ctx).Create(withdefault.FissionUserActive(&model.FissionUserActive{ CampaignID: req.GetCampaignId(), UserID: req.GetUserId(), LastActive: time.Now().Unix(), })) if err != nil { err = s.BE().MysqlError(err) return } return } _, err = m.WithContext(s.ctx).Where(m.ID.Eq(info.ID)).UpdateSimple(m.LastActive.Value(time.Now().Unix())) if err != nil { err = s.BE().MysqlError(err) return } *res = pb.ActiveRes{} return } // ChildBP 应用内埋点 func (s *WCampaignStat) ChildBP(req *pb.ChildBPReq, res *pb.ChildBPRes) (err error) { defer s.checkErr() cpn, err := cache.NewCampaign(s.ctx).FindById(req.GetCampaiginId()) if err != nil { err = s.BE().CacheError(err) return } if cpn == nil || !verify.InArray(cpn.Status, mtype.FissionCampaignStatusPub, mtype.FissionCampaignStatusPubPre) || cpn.ReportType != mtype.FissionCampaignReportTypeNew { return } user, err := cache.NewFissionUser(s.ctx, cpn.ID).FindById(req.GetUserId()) if err != nil { err = s.BE().CacheError(err) return } if user == nil || user.IsView == mtype.Yes { return } childCpn, err := cache.NewCampaign(s.ctx).FindByHashId(req.GetChildHashId()) if err != nil { err = s.BE().CacheError(err) return } if childCpn == nil || !verify.InArray[int8](childCpn.Status, mtype.FissionCampaignStatusPub, mtype.FissionCampaignStatusPubPre) { return } childUser, err := cache.NewFissionChildUser(s.ctx).FindByUniqIdx(user.ID, childCpn.ID) if err != nil { err = s.BE().CacheError(err) return } if childUser == nil { return } userBp := fissionaction.NewMarkPoint(s.ctx).InApp(user) childBp := fissionaction.NewMarkPoint(s.ctx).Child(childUser, user) //支持埋点类型(43-点击子活动入口) switch req.GetType() { case mtype.FissionActionTypeChildShow: userBp.ClickChild(time.Now().Unix(), cpn.ID, childCpn.ChildType) childBp.ChildShow(time.Now().Unix()) default: } *res = pb.ChildBPRes{} return } // ChildReportInfo 子活动报表信息 func (s *WCampaignStat) ChildReportInfo(req *pb.ChildReportInfoReq, res *pb.ChildReportInfoRes) (err error) { defer s.checkErr() cpn, err := cache.NewCampaign(s.ctx).FindByHashId(req.GetHashId()) if err != nil { err = s.BE().CacheError(err) return } if cpn == nil || cpn.Target != mtype.FissionCampaignConfigTargetChild { return } var pTitle string if cpn.Pid > 0 { var pcpn *model.FissionCampaign pcpn, err = cache.NewCampaign(s.ctx).FindById(cpn.Pid) if err != nil { err = s.BE().CacheError(err) return } if pcpn != nil { pTitle = pcpn.Title } } *res = pb.ChildReportInfoRes{ HashId: cpn.HashID, Title: cpn.Title, StartTime: cpn.TStart, EndTime: cpn.TEnd, Status: int32(cpn.Status), TOffset: cpn.TOffset, ChildType: int32(cpn.ChildType), PTitle: pTitle, } return }