package service import ( "context" "fmt" "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/os/gtime" "github.com/gogf/gf/v2/util/gconv" "time" v1 "vistor/api/v1" "vistor/internal/consts" "vistor/internal/dao" "vistor/internal/model" ) type visitorService struct{} var Visitor = visitorService{} //var statisticType = g.Map{ // "day": //} type IVisitor interface { VisitorAccess(ctx context.Context, req *v1.VisitorAccessReq) error VisitorStatistic(ctx context.Context, req *v1.VisitorAccessReq) (res *v1.VisitorAccessRes, err error) } func (s *visitorService) VisitorAccess(ctx context.Context, req *v1.VisitorAccessReq) error { insert, err := dao.VisitorRecord.Ctx(ctx).Data(req).Insert() affected, err := insert.RowsAffected() if err != nil { return err } if affected == 0 { return gerror.Newf("提交失败,请重试") } return nil } func (s *visitorService) VisitorStatistic(ctx context.Context, req *v1.VisitorStatisticReq) (res *v1.VisitorStatisticRes, err error) { var ( resRecords []*model.ResRecord ) db := g.DB() xAxis := g.SliceStr{} yAxis := g.SliceStr{} condition := g.Map{} if req.VisitorName != "" { condition["vr.visitor_name"] = req.VisitorName } if req.VisitorIdentity != "" { condition["vr.visitor_identity"] = req.VisitorIdentity } if req.VisitorPhone != "" { condition["vr.visitor_phone"] = req.VisitorPhone } if req.StatisticType == consts.StatisticTypeDay { startDate := gconv.Int(gtime.New(req.EndDate).Format("Ymd")) endDate := gconv.Int(gtime.New(req.StartDate).Format("Ymd")) duration := startDate - endDate + 1 for i := 0; duration > i; i++ { xAxis = append(xAxis, gtime.New(req.StartDate).AddDate(0, 0, i).Format("Y-m-d")) } fields := "id,visitor_name,visitor_identity,visitor_phone,visit_at,from_unixtime(visit_at,'%Y-%m-%d') visit_date" subQuery := db.Model("visitor_record vr"). Where(condition). WhereBetween("vr.visit_at", req.StartDate, req.EndDate). Fields(fields) mainQuery := db.Model("? as v", subQuery) err = mainQuery. Fields("count(v.id) y_axis, v.visit_date x_axis"). Group("x_axis"). Order("x_axis"). Scan(&resRecords) if err != nil { return nil, err } for _, x := range xAxis { y := "0" for _, record := range resRecords { if record.XAxis == x { y = record.YAxis } } yAxis = append(yAxis, y) } } else { var weekNum, monthNum, yearNum int if req.StatisticType == consts.StatisticTypeWeek { switch req.SubType { case consts.SubTypeLast4Week: weekNum = 4 case consts.SubTypeLast8Week: weekNum = 8 case consts.SubTypeLast12Week: weekNum = 12 } //获取按周统计数据 xAxis, yAxis = s.getWeekStatistic(ctx, weekNum, condition) } else if req.StatisticType == consts.StatisticTypeMonth { switch req.SubType { case consts.SubTypeLast4Month: monthNum = 4 case consts.SubTypeLast8Month: monthNum = 8 case consts.SubTypeLast12Month: monthNum = 12 } //获取按月统计数据 xAxis, yAxis = s.getMonthStatistic(ctx, monthNum, condition) } else if req.StatisticType == consts.StatisticTypeYear { switch req.SubType { case consts.SubTypeLastYear: yearNum = 1 case consts.SubTypeLast2Year: yearNum = 2 case consts.SubTypeLast3Year: yearNum = 3 } //获取按年统计数据 xAxis, yAxis = s.getYearStatistic(ctx, yearNum, condition) } } res = &v1.VisitorStatisticRes{ XAxis: xAxis, YAxis: yAxis, } return } func (s *visitorService) getYearStatistic(ctx context.Context, lastYearNum int, condition g.Map) (xAxis g.SliceStr, yAxis g.SliceStr) { for ; 1 <= lastYearNum; lastYearNum-- { //获取当年第一天 yearStart := gtime.New(gtime.Now().AddDate(-(lastYearNum - 1), 0, 0).Format("Y-01-01 00:00:00")).Unix() yearEnd := gtime.New(gtime.Now().AddDate(-(lastYearNum - 2), 0, 0).Format("Y-01-01 00:00:00")).Unix() count, err := dao.VisitorRecord.Ctx(ctx).As("vr").Where(condition).WhereBetween(dao.VisitorRecord.Columns().VisitAt, yearStart, yearEnd).Count() if err != nil { return g.SliceStr{}, g.SliceStr{} } //获取统计数据 xAxis = append(xAxis, gtime.New(yearStart).Format("Y")) yAxis = append(yAxis, gconv.String(count)) } return } func (s *visitorService) getMonthStatistic(ctx context.Context, lastMonthNum int, condition g.Map) (xAxis g.SliceStr, yAxis g.SliceStr) { for ; 1 <= lastMonthNum; lastMonthNum-- { //获取当月第一天 monthStart := gtime.New(gtime.Now().AddDate(0, -(lastMonthNum - 1), 0).Format("Y-m-01 00:00:00")).Unix() monthEnd := gtime.New(gtime.Now().AddDate(0, -(lastMonthNum - 2), 0).Format("Y-m-01 00:00:00")).Unix() count, err := dao.VisitorRecord.Ctx(ctx).As("vr").Where(condition).WhereBetween(dao.VisitorRecord.Columns().VisitAt, monthStart, monthEnd).Count() if err != nil { return g.SliceStr{}, g.SliceStr{} } //获取统计数据 xAxis = append(xAxis, gtime.New(monthStart).Format("Y-m")) yAxis = append(yAxis, gconv.String(count)) } return } func (s *visitorService) getWeekStatistic(ctx context.Context, lastWeekNum int, condition g.Map) (xAxis g.SliceStr, yAxis g.SliceStr) { for ; 1 <= lastWeekNum; lastWeekNum-- { weekDate, startTimestamp := s.getLastWeekFirstDate(lastWeekNum) endTimestamp := gtime.New(weekDate).AddDate(0, 0, 7).Unix() count, err := dao.VisitorRecord.Ctx(ctx).As("vr").Where(condition).WhereBetween(dao.VisitorRecord.Columns().VisitAt, startTimestamp, endTimestamp).Count() if err != nil { return g.SliceStr{}, g.SliceStr{} } //获取第几周 _, weekNum := gtime.New(weekDate).ISOWeek() xAxis = append(xAxis, fmt.Sprintf("第%d周", weekNum)) yAxis = append(yAxis, gconv.String(count)) } return } /* * 获取本周周一的日期 */ func (s *visitorService) getFirstDateOfWeek() (weekMonday string, dateTimestamp int64) { now := time.Now() offset := int(time.Monday - now.Weekday()) if offset > 0 { offset = -6 } weekStartDate := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, time.Local).AddDate(0, 0, offset) weekMonday = weekStartDate.Format("2006-01-02") dateTimestamp = gtime.New(weekMonday).Unix() return } /* * 获取本周周一的日期 */ func (s *visitorService) getLastWeekFirstDate(weekNum int) (weekMonday string, dateTimestamp int64) { thisWeekMonday, _ := s.getFirstDateOfWeek() TimeMonday, _ := time.Parse("2006-01-02", thisWeekMonday) lastWeekMonday := TimeMonday.AddDate(0, 0, -7*(weekNum-1)) weekMonday = lastWeekMonday.Format("2006-01-02") dateTimestamp = gtime.New(weekMonday).Unix() return }