package service import ( "joybuywork/internal/app" "joybuywork/internal/consts" "joybuywork/internal/consts/ckey" "joybuywork/internal/repository/dbcheck" "joybuywork/internal/repository/model" "joybuywork/internal/repository/mtype" "joybuywork/internal/repository/withdefault" containers "joybuywork/internal/service/containers/games" "joybuywork/internal/utils" "joybuywork/internal/utils/blink" pb "joybuywork/proto/go_proto/w_games" "fmt" "strings" "time" "github.com/golang-module/carbon/v2" "gorm.io/gen/field" ) type WGames struct { Service } // LinkList 链接列表 func (s *WGames) LinkList(req *pb.LinkListReq, res *pb.LinkListRes) (err error) { defer s.checkErr() project, err := s.ProjectErrNil(req.GetProjectHashId()) if err != nil { return } _, gameMap := consts.GameLinkMap() m := s.GetDao().GameLink list, err := m.WithContext(s.ctx).Where(m.ProjectID.Eq(project.ID), m.GameID.Eq(req.GetGameId()), m.IsDel.Eq(mtype.No)).Find() if err != nil { return } var playLinkMap = make(map[int64]string, len(list)) for _, v := range list { playLinkMap[v.ID] = blink.NewGameLink(gameMap[v.GameID].Link, project.HashID, blink.SetGameLinkId(v.HashID)).Link() } *res = pb.LinkListRes{ List: make([]*pb.LinkListRes_One, 0, len(list)), } for _, v := range list { res.List = append(res.List, &pb.LinkListRes_One{ Id: v.ID, Title: v.Title, IsDefault: int32(v.IsDefault), Link: playLinkMap[v.ID], }) } return } // Visit 访问小游戏 func (s *WGames) Visit(req *pb.VisitReq, res *pb.VisitRes) (err error) { defer s.checkErr() *res = pb.VisitRes{} container := new(containers.Visit) { container.Init(s.ctx) container.Req = req container.Res = res } return container.Run() } // List 游戏列表 func (s *WGames) List(req *pb.ListReq, res *pb.ListRes) (err error) { defer s.checkErr() project, err := s.ProjectErrNil(req.GetProjectHashId()) if err != nil { return } games := consts.Games ids, gameMap := consts.GameLinkMap() m := s.GetDao().GameLink list, err := m.WithContext(s.ctx).Where(m.ProjectID.Eq(project.ID), m.GameID.In(ids...), m.IsDel.Eq(mtype.No), m.IsDefault.Eq(mtype.Yes)).Find() if err != nil { return } var linkMap = make(map[int64]*model.GameLink) for _, v := range list { linkMap[v.GameID] = v } var playLinkMap = make(map[int64]string, len(games)) for _, id := range ids { link, ok := linkMap[id] if !ok { lc := app.NewFollower(s.ctx, ckey.GameLinkInit(project.ID, id)) if ok1, _ := lc.SoftLock(); ok1 { link = withdefault.GameLink(&model.GameLink{ ProjectID: project.ID, GameID: id, Title: "默认链接", IsDefault: mtype.Yes, }) err = m.WithContext(s.ctx).Create(link) if err != nil { return } lc.Release() } } playLinkMap[id] = blink.NewGameLink(gameMap[id].Link, project.HashID, blink.SetGameLinkId(link.HashID)).Link() } *res = pb.ListRes{ List: make([]*pb.ListRes_One, 0, len(games)), } for _, v := range games { res.List = append(res.List, &pb.ListRes_One{ Id: v.ID, Title: v.Title, Img: v.Img, Link: playLinkMap[v.ID], }) } return } // LinkStore 创建链接 func (s *WGames) LinkStore(req *pb.LinkStoreReq, res *pb.LinkStoreRes) (err error) { defer s.checkErr() project, err := s.ProjectErrNil(req.GetProjectHashId()) if err != nil { return } link := withdefault.GameLink(&model.GameLink{ ProjectID: project.ID, GameID: req.GetGameId(), Title: req.GetTitle(), }) err = s.GetDao().GameLink.WithContext(s.ctx).Create(link) if err != nil { err = s.BE().MysqlError(err) return } _, gameMap := consts.GameLinkMap() *res = pb.LinkStoreRes{ Id: link.ID, Link: blink.NewGameLink(gameMap[link.GameID].Link, project.HashID, blink.SetGameLinkId(link.HashID)).Link(), } return } // LinkUpdate 更新链接 func (s *WGames) LinkUpdate(req *pb.LinkUpdateReq, res *pb.LinkUpdateRes) (err error) { defer s.checkErr() project, err := s.ProjectErrNil(req.GetProjectHashId()) if err != nil { return } m := s.GetDao().GameLink link, err := m.WithContext(s.ctx).Where(m.ID.Eq(req.GetId()), m.IsDel.Eq(mtype.No)).Take() if err = dbcheck.DbError(err); err != nil { err = s.BE().MysqlError(err) return } if link == nil || link.ProjectID != project.ID { err = s.BE().VerifyError("not found link") return } var up []field.AssignExpr if link.Title != req.GetTitle() { up = append(up, m.Title.Value(req.GetTitle())) } if len(up) > 0 { _, err = m.WithContext(s.ctx).Where(m.ID.Eq(link.ID)).UpdateSimple(up...) if err != nil { err = s.BE().MysqlError(err) return } } *res = pb.LinkUpdateRes{ Id: link.ID, } return } // LinkDestroy 删除链接 func (s *WGames) LinkDestroy(req *pb.LinkDestroyReq, res *pb.LinkDestroyRes) (err error) { defer s.checkErr() project, err := s.ProjectErrNil(req.GetProjectHashId()) if err != nil { return } m := s.GetDao().GameLink link, err := m.WithContext(s.ctx).Where(m.ID.Eq(req.GetId()), m.IsDel.Eq(mtype.No)).Take() if err = dbcheck.DbError(err); err != nil { err = s.BE().MysqlError(err) return } if link == nil || link.ProjectID != project.ID || link.IsDefault == mtype.Yes { return } _, err = m.WithContext(s.ctx).Where(m.ID.Eq(link.ID)).UpdateSimple(m.IsDel.Value(mtype.Yes)) if err != nil { err = s.BE().MysqlError(err) return } *res = pb.LinkDestroyRes{ Id: link.ID, } return } // Trace 跟踪小游戏 func (s *WGames) Trace(req *pb.TraceReq, res *pb.TraceRes) (err error) { defer s.checkErr() *res = pb.TraceRes{} container := new(containers.Trace) { container.Init(s.ctx) container.Req = req container.Res = res } return container.Run() } // Overview 小游戏统计 func (s *WGames) Overview(req *pb.OverviewReq, res *pb.OverviewRes) (err error) { defer s.checkErr() project, err := s.ProjectErrNil(req.GetProjectHashId()) if err != nil { return } m := s.GetDao().GameTotal total, err := m.WithContext(s.ctx).Where( m.ProjectID.Eq(project.ID), m.GameID.Eq(req.GetGameId()), m.LinkID.Eq(req.GetLinkId()), ).Take() if err = dbcheck.DbError(err); err != nil { err = s.BE().MysqlError(err) return } dateM := s.GetDao().GameTotalDate yes := carbon.Now().SubDay().Format(time.DateOnly) yesterdayTotal, err := dateM.WithContext(s.ctx).Where( dateM.ProjectID.Eq(project.ID), dateM.GameID.Eq(req.GetGameId()), dateM.LinkID.Eq(req.GetLinkId()), dateM.Ymd.Eq(yes), ).Take() if err = dbcheck.DbError(err); err != nil { err = s.BE().MysqlError(err) return } var mark = []string{"visit_num", "visit_user_num", "total_stay"} *res = pb.OverviewRes{ List: make([]*pb.OverviewRes_One, 0, len(mark)), } for _, v := range mark { one := &pb.OverviewRes_One{ Mark: v, Total: 0, Yesterday: 0, Avg: "", } switch v { case "visit_num": if total != nil { one.Total = total.Pv } if yesterdayTotal != nil { one.Yesterday = yesterdayTotal.Pv } case "visit_user_num": if total != nil { one.Total = total.Uv } if yesterdayTotal != nil { one.Yesterday = yesterdayTotal.Uv } case "total_stay": if total != nil { one.Total = total.Psec one.Avg = strings.TrimSuffix(strings.TrimRight(fmt.Sprintf("%.2f", float64(total.Psec)/float64(total.Uv)), "0"), ".") } } res.List = append(res.List, one) } return } // Trend 小游戏趋势 func (s *WGames) Trend(req *pb.TrendReq, res *pb.TrendRes) (err error) { defer s.checkErr() project, err := s.ProjectErrNil(req.GetProjectHashId()) if err != nil { return } start := utils.Ternary(req.GetStartTime() != 0, carbon.CreateFromTimestamp(req.GetStartTime()), carbon.Now().StartOfDay()) end := utils.Ternary(req.GetEndTime() != 0, carbon.CreateFromTimestamp(req.GetEndTime()), carbon.Now()) var xMap = make(map[string]int) x := utils.BetweenDay(start, end, time.DateOnly) for k, v := range x { xMap[v] = k } m := s.GetDao().GameTotalDate list, err := m.WithContext(s.ctx).Where( m.ProjectID.Eq(project.ID), m.GameID.Eq(req.GetGameId()), m.LinkID.Eq(req.GetLinkId()), m.Ymd.Between(x[0], x[len(x)-1]), ).Find() if err != nil { return } var y []*pb.TrendRes_Y for _, v := range list { visitNum := &pb.TrendRes_Y{ Type: "visit_num", Data: make([]int64, len(x)), } visitNum.Data[xMap[v.Ymd]] = v.Pv visitUserNum := &pb.TrendRes_Y{ Type: "visit_user_num", Data: make([]int64, len(x)), } visitUserNum.Data[xMap[v.Ymd]] = v.Uv y = append(y, visitNum, visitUserNum) } *res = pb.TrendRes{ X: x, Y: y, } return }