package task import ( "context" "encoding/json" "fmt" "github.com/gogf/gf/v2/database/gdb" "github.com/gogf/gf/v2/os/glog" "github.com/gogf/gf/v2/util/gconv" "github.com/gogf/gf/v2/util/guid" "server/internal/consts" "server/internal/dao" "server/internal/model" "server/internal/model/do" "server/internal/service" "server/utility/ecode" "server/utility/gamelife" "server/utility/snowid" "sort" "strconv" "strings" "sync" "time" ) type sTask struct{} func New() service.ITask { return &sTask{} } func init() { service.RegisterTask(New()) } func (s *sTask) UserTaskRankingList(ctx context.Context, in *model.UserTaskRankingIn) (out *model.UserTaskRankingOut, err error) { // 判断排行类型 var start, end time.Time if in.Type == 1 { // 日 now := time.Now() // 当天开始时间 start = time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location()) // 当天结束时间 end = time.Date(now.Year(), now.Month(), now.Day(), 23, 59, 59, 0, now.Location()) } else if in.Type == 2 { // 周 now := time.Now() loc := now.Location() weekday := int(now.Weekday()) if weekday == 0 { // 周日是0 weekday = 7 } // 本周开始时间(周一 00:00:00) start = time.Date(now.Year(), now.Month(), now.Day()-weekday+1, 0, 0, 0, 0, loc) // 本周结束时间(周日 23:59:59) end = time.Date(now.Year(), now.Month(), now.Day()-weekday+7, 23, 59, 59, 0, loc) } else if in.Type == 3 { // 月 now := time.Now() loc := now.Location() // 本月开始时间(1号 00:00:00) start = time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, loc) // 下月1号 nextMonth := start.AddDate(0, 1, 0) // 本月结束时间(本月最后一天 23:59:59) end = nextMonth.Add(-time.Second) } else { return nil, ecode.Params.Sub("排行方式错误") } m := dao.UserTasks.Ctx(ctx) // 构建查询条件 if in.Page == 0 { in.Page = 1 } if in.Size == 0 { in.Size = 10 } if in.StoreId > 0 { m = m.Where(dao.UserTasks.Columns().StoreId, in.StoreId) } else if in.NetBarAccount != "" && in.StoreId <= 0 { value, err := dao.Stores.Ctx(ctx).Where(dao.Stores.Columns().NetbarAccount, in.NetBarAccount).Fields(dao.Stores.Columns().Id).Value() if err != nil { return nil, ecode.Fail.Sub("查询门店ID失败") } if value.IsEmpty() { return nil, ecode.Fail.Sub("门店不存在") } m = m.Where(dao.UserTasks.Columns().StoreId, value.Int()) } list := make([]model.UserTaskRankingArgs, 0) var total int // SELECT `uid`,`nickname` FROM `user` ORDER BY `uid` asc err = m.Page(in.Page, in.Size).LeftJoin(dao.Users.Table(), fmt.Sprintf("`%s`.`id` = `%s`.`user_id`", dao.Users.Table(), dao.UserTasks.Table())). Fields("username,avatar,count(*) num").Where(dao.UserTasks.Columns().Status, 2). WhereBetween(dao.UserTasks.Columns().CompletedAt, start, end).OrderDesc("num").OrderDesc("username").Group("user_id"). ScanAndCount(&list, &total, false) if err != nil { return nil, ecode.Fail.Sub("查询排行榜失败") } // 判断登录查询当前任务完成数量,排名 var rankingNum int var loginUserRanking []model.LoginUserRanking var loginUserRankingNum model.LoginUserRankingNum if in.OperatorId != 0 { value, err := dao.UserTasks.Ctx(ctx).Fields("count(*) num").Where(dao.UserTasks.Columns().UserId, in.OperatorId).Where(dao.UserTasks.Columns().StoreId, in.StoreId).Where(dao.UserTasks.Columns().Status, 2). WhereBetween(dao.UserTasks.Columns().CompletedAt, start, end).Group("user_id"). Value() if err != nil { return nil, ecode.Fail.Sub("查询当前登录用户完成数失败") } if value.IsEmpty() { loginUserRankingNum.Num = 0 } else { loginUserRankingNum.Num = value.Int() } err = dao.UserTasks.Ctx(ctx).LeftJoin(dao.Users.Table(), fmt.Sprintf("`%s`.`id` = `%s`.`user_id`", dao.Users.Table(), dao.UserTasks.Table())). Fields("username,count(*) num").Where(dao.UserTasks.Columns().StoreId, in.StoreId).Where(dao.UserTasks.Columns().Status, 2). WhereBetween(dao.UserTasks.Columns().CompletedAt, start, end).OrderDesc("num").OrderDesc("username").Group("user_id"). Scan(&loginUserRanking) if err != nil { return nil, ecode.Fail.Sub("查询当前登录用户排名失败") } // 查找当前登录用户排名 //index := sort.Search(len(loginUserRanking), func(i int) bool { // return loginUserRanking[i].Num <= loginUserRankingNum.Num //}) index, flag := sort.Find(len(loginUserRanking), func(i int) int { return strings.Compare(strconv.Itoa(loginUserRanking[i].Num), strconv.Itoa(loginUserRankingNum.Num)) }) if flag { rankingNum = index + 1 } } return &model.UserTaskRankingOut{ List: list, Total: total, CompletedNum: loginUserRankingNum.Num, RankingNum: rankingNum, }, nil } // GetNonLoginTaskList 获取下发到指定网吧的任务列表(未登录) func (s *sTask) GetNonLoginTaskList(ctx context.Context, in *model.GetTaskListIn) (out *model.GetTaskListOut, err error) { // 调用外部接口 activity, err := gamelife.GetGamelifeClient(ctx).RequestActivity(ctx, &model.QQNetbarActivityIn{ServiceName: consts.GetNonLoginTaskList, TaskParam: model.TaskParam{Gid: in.Gid, NetBarAccount: in.NetBarAccount, Num: in.Num, Pageidx: in.Pageidx}}) if err != nil { return nil, err } result, ok := activity.(*model.GameTaskResponse) if !ok { return nil, ecode.Fail.Sub("数据类型转换失败") } // 剔除不需要的任务数据 var tasks []model.Task idx := result.PageIdx //for _, task := range result.TaskList { // //data := model.Task{ // // QqNetbarTaskId: task.TaskID, // // QqNetbarTaskName: task.Title, // // QqNetbarTaskMemo: task.TaskDesc, // // QqNetbarTaskRules: task.RuleDesc, // // QqNetbarTargetName: task.TargetName, // // QqNetbarTargetTime: task.TargetTimes, // // StartTime: task.CycleStart, // // EndTime: task.CycleEnd, // //} // // // 组装奖励数据 // err := dao.TaskRewards.Ctx(ctx). // LeftJoin(dao.Rewards.Table(), // fmt.Sprintf("`%s`.`%s` = `%s`.`%s` ", // dao.Rewards.Table(), dao.Rewards.Columns().Id, // dao.TaskRewards.Table(), dao.TaskRewards.Columns().RewardId, // ), // ).Fields( // fmt.Sprintf( // "%s.*", // dao.Rewards.Table(), // ), // ).Where(dao.TaskRewards.Columns().TaskId, task.TaskID).Scan(&data.Rewards) // if err != nil { // return nil, err // } // tasks = append(tasks, data) //} return &model.GetTaskListOut{ PageIdx: idx, Data: tasks, }, nil } func (s *sTask) GetLoginTaskList(ctx context.Context, in *model.GetTaskListIn) (out *model.GetTaskListOut, err error) { // 调用外部接口 activity, err := gamelife.GetGamelifeClient(ctx).RequestActivity(ctx, &model.QQNetbarActivityIn{ServiceName: consts.GetTaskList, PopenId: in.PopenId, BindType: in.BindType, TaskParam: model.TaskParam{Gid: in.Gid, NetBarAccount: in.NetBarAccount, Num: in.Num, Pageidx: in.Pageidx}}) if err != nil { return nil, err } result, ok := activity.(*model.GameTaskResponse) if !ok { return nil, ecode.Fail.Sub("数据类型转换失败") } pageIdx := result.PageIdx // 剔除不需要的任务数据 var tasks []model.Task //for _, task := range result.TaskList { // data := model.Task{ // QqNetbarTaskId: task.TaskID, // QqNetbarTaskName: task.Title, // QqNetbarTaskMemo: task.TaskDesc, // QqNetbarTaskRules: task.RuleDesc, // QqNetbarTargetName: task.TargetName, // QqNetbarTargetTime: task.TargetTimes, // StartTime: task.CycleStart, // EndTime: task.CycleEnd, // //Status: task.Status, // } // data.UserTaskResult.Usertimes = task.UserTimes // // 组装门店奖励数据 // err := dao.TaskRewards.Ctx(ctx). // LeftJoin(dao.Rewards.Table(), // fmt.Sprintf("`%s`.`%s` = `%s`.`%s`", // dao.Rewards.Table(), dao.Rewards.Columns().Id, // dao.TaskRewards.Table(), dao.TaskRewards.Columns().RewardId)). // LeftJoin(dao.RewardTypes.Table(), // fmt.Sprintf("`%s`.`%s` = `%s`.`%s`", // dao.RewardTypes.Table(), dao.RewardTypes.Columns().Id, // dao.Rewards.Table(), dao.Rewards.Columns().RewardTypeId)). // Fields( // fmt.Sprintf("%s.*, `%s`.`%s` AS %s", // dao.Rewards.Table(), // dao.RewardTypes.Table(), dao.RewardTypes.Columns().Name, // "reward_type_name", // ), // ).Where(dao.TaskRewards.Columns().TaskId, task.TaskID).Scan(&data.Rewards) // if err != nil { // return nil, err // } // // // 任务状态=1或者2不做操作,其他查询门店奖励是否全部领取 // if task.Status != 1 && task.Status != 2 { // count, err := dao.UserTasks.Ctx(ctx).Where(dao.UserTasks.Columns().TaskId, task.TaskID).Where(dao.UserTasks.Columns().UserId, in.UserId).LeftJoin(dao.UserTaskRewards.Table(), // fmt.Sprintf("%s.user_tasks_id = %s.id", dao.UserTaskRewards.Table(), dao.UserTasks.Table())).LeftJoin(dao.Rewards.Table(), fmt.Sprintf("%s.id = %s.reward_id", // dao.Rewards.Table(), dao.UserTaskRewards.Table())).Where(dao.Rewards.Columns().Source, 2).Where(dao.UserTaskRewards.Columns().Status, 2).Count() // if err != nil { // return nil, ecode.Fail.Sub("查询用户门店任务奖励失败") // } // // if count > 0 { // data.Status = 2 // } else { // data.Status = 3 // } // } else { // data.Status = task.Status // } // tasks = append(tasks, data) // // // 根据用户完成次数和任务指标次数判任务是否完成,修改任务记录状态为 3 // if int(task.UserTimes) >= task.TargetTimes { // _, err := dao.UserTasks.Ctx(ctx).Where(do.UserTasks{TaskId: task.TaskID}).Where(do.UserTasks{UserId: in.UserId}).Data(do.UserTasks{Status: 3}).Update() // if err != nil { // return nil, ecode.Fail.Sub("更新用户任务记录状态异常") // } // } //} return &model.GetTaskListOut{ Data: tasks, PageIdx: pageIdx, }, err } // GetTaskCompletedList 获取用户任务完成列表 func (s *sTask) GetTaskCompletedList(ctx context.Context, in *model.TaskListIn) (out *model.TaskListOut, err error) { m := dao.UserTasks.Ctx(ctx) var data []model.UserTask var total int if in.StoreId > 0 { m = m.Where(dao.UserTasks.Columns().StoreId, in.StoreId) } //err = m.Page(in.Page, in.Size).Fields(fmt.Sprintf("%s.*, %s.*,%s.*, %s.*", dao.UserTasks.Table(), dao.Users.Table(), dao.Stores.Table(), dao.Games.Table())). // LeftJoin(dao.Users.Table(), fmt.Sprintf("`%s`.`id` = `%s`.`user_id`", dao.Users.Table(), dao.UserTasks.Table())). // LeftJoin(dao.Stores.Table(), fmt.Sprintf("`%s`.`id` = `%s`.`store_id`", dao.Stores.Table(), dao.UserTasks.Table())). // LeftJoin(dao.Games.Table(), fmt.Sprintf("`%s`.`game_id` = `%s`.`game_id`", dao.Games.Table(), dao.UserTasks.Table())).WithAll().ScanAndCount(&data, &total, false) err = m.Page(in.Page, in.Size).WithAll().ScanAndCount(&data, &total, false) if err != nil { return nil, ecode.Fail.Sub("获取已完成任务列表失败") } return &model.TaskListOut{ List: data, Total: total, }, nil } func (s *sTask) GetSelectorList(ctx context.Context, in *model.SelectorIn) (out *[]model.SelectorOut, err error) { data := make([]model.SelectorOut, 0) err = dao.Merchants.Ctx(ctx).WithAll().Scan(&data) for i, v := range data { for j, vv := range v.StoreDatas { str, err := dao.Stores.Ctx(ctx).Fields("name").One(do.Stores{Id: vv.Id}) if err != nil { return nil, ecode.Fail.Sub("获取门店名称失败") } data[i].StoreDatas[j].StoreName = str.Map()["name"].(string) } } if err != nil { return nil, ecode.Fail.Sub("获取选择列表失败") } return &data, nil } // GetTask 完成任务 func (s *sTask) GetTask(ctx context.Context, in *model.GetTaskIn) (out *model.GetTaskOut, err error) { var storeId int if in.StoreId > 0 { storeId = in.StoreId } else if in.NetBarAccount != "" && in.StoreId <= 0 { value, err := dao.Stores.Ctx(ctx).Where(do.Stores{NetbarAccount: in.NetBarAccount}).Fields(dao.Stores.Columns().Id).Value() if err != nil { return nil, ecode.Fail.Sub("获取门店ID异常") } if value.IsEmpty() { return nil, ecode.Fail.Sub("获取门店ID异常") } storeId = value.Int() } var userTask []*model.UserTask err = dao.UserTasks.Ctx(ctx).Where(do.UserTasks{UserId: in.UserId, TaskId: in.TaskId, StoreId: storeId, GameId: in.GameId}).WhereNot("status", 3).Scan(&userTask) if err != nil { return nil, ecode.Fail.Sub("查询用户该任务记录失败") } if userTask != nil { return nil, ecode.Fail.Sub("该任务记录已存在") } // TODO 流水号未知 serialNumber, err := snowid.GetSnowClient().GenerateSerialNumber() if err != nil { return nil, ecode.Fail.Sub("生成流水号异常") } if err = dao.UserTasks.Transaction(ctx, func(ctx context.Context, tx gdb.TX) (err error) { // 创建任务记录 id, err := dao.UserTasks.Ctx(ctx).InsertAndGetId(do.UserTasks{ UserId: in.UserId, TaskId: in.TaskId, StoreId: storeId, Status: 1, SerialNumber: serialNumber, TaskName: in.TaskName, GameId: in.GameId, }) if err != nil { return ecode.Fail.Sub("创建用户任务记录失败") } // 查询该任务相关联的奖励, 创建对应奖励下发记录id array, err := dao.TaskRewards.Ctx(ctx).LeftJoin(dao.Rewards.Table(), "rewards.id = task_rewards.reward_id").Where(do.TaskRewards{TaskId: in.TaskId}).Fields(dao.TaskRewards.Columns().RewardId).Fields(dao.Rewards.Columns().Name).All() if err != nil { return ecode.Fail.Sub("获取任务关联奖励列表失败") } for _, v := range array { _, err = dao.UserTaskRewards.Ctx(ctx).Data(do.UserTaskRewards{ UserTaskId: id, RewardId: v["reward_id"].Int64(), RewardName: v["name"].String(), Status: consts.RewardInitStatus, InnerOrderId: fmt.Sprintf("reward%s", guid.S()), }).Insert() if err != nil { return ecode.Fail.Sub("创建用户任务奖励记录失败") } } return }); err != nil { return nil, err } return &model.GetTaskOut{ Success: true, }, nil } func (s *sTask) GetUserTaskRecordsList(ctx context.Context, in *model.UserTaskRecordsListIn) (out *model.UserTaskRecordsListOut, err error) { list := make([]model.UserTask2, 0) var total int orm := dao.UserTasks.Ctx(ctx).Where(dao.UserTasks.Columns().UserId, in.UserId) if in.StoreId != 0 && in.NetBarAccount == "" { orm = orm.Where(dao.UserTasks.Columns().StoreId, in.StoreId) } if in.NetBarAccount != "" && in.StoreId == 0 { value, err := dao.Stores.Ctx(ctx).Where(do.Stores{NetbarAccount: in.NetBarAccount}).Fields(dao.Stores.Columns().Id).Value() if err != nil { return nil, err } orm = orm.Where(dao.UserTasks.Columns().StoreId, value.Int()) } if in.GameId != 0 { orm = orm.Where(dao.UserTasks.Columns().GameId, in.GameId) } err = orm.Page(in.Page, in.Size).ScanAndCount(&list, &total, false) if err != nil { return nil, ecode.Fail.Sub("获取用户任务列表失败") } return &model.UserTaskRecordsListOut{ List: list, Total: total, }, nil } // GetTaskList PC-WEB获取任务列表 func (s *sTask) GetTaskList(ctx context.Context, in *model.GetTaskListV2In) (out *model.GetTaskListV2Out, err error) { var tasks []model.Task var pageIdx string var data []model.GameTask if in.IsBound == 0 { // 未绑定游戏查询自己数据库 err := dao.Tasks.Ctx(ctx).Where(do.Tasks{GameId: in.Gid, NetbarAcconut: in.NetBarAccount}).WithAll().WithAll().Scan(&tasks) if err != nil { return nil, ecode.Fail.Sub("获取任务列表失败") } for i, v := range tasks { err := json.Unmarshal([]byte(v.Task), &tasks[i].GameTask) if err != nil { return nil, ecode.Fail.Sub("解析任务信息失败") } tasks[i].Task = "" } return &model.GetTaskListV2Out{ Data: tasks, }, nil } else { // 已绑定 // 调用外部接口 activity, err := gamelife.GetGamelifeClient(ctx).RequestActivity(ctx, &model.QQNetbarActivityIn{ServiceName: consts.GetTaskList, PopenId: in.PopenId, BindType: in.BindType, TaskParam: model.TaskParam{Gid: in.Gid, NetBarAccount: in.NetBarAccount, Num: in.Num, Pageidx: in.Pageidx}}) if err != nil { return nil, err } result, ok := activity.(*model.GameTaskResponse) if !ok { return nil, ecode.Fail.Sub("数据类型转换失败") } pageIdx = result.PageIdx // 剔除不需要的任务数据 for i, task := range result.TaskList { //data := model.Task{ // QqNetbarTaskId: task.TaskID, // QqNetbarTaskName: task.Title, // QqNetbarTaskMemo: task.TaskDesc, // QqNetbarTaskRules: task.RuleDesc, // QqNetbarTargetName: task.TargetName, // QqNetbarTargetTime: task.TargetTimes, // StartTime: task.CycleStart, // EndTime: task.CycleEnd, // //Status: task.Status, //} //data.UserTaskResult.Usertimes = task.UserTimes // 组装门店奖励数据 err := dao.TaskRewards.Ctx(ctx). LeftJoin(dao.Rewards.Table(), fmt.Sprintf("`%s`.`%s` = `%s`.`%s`", dao.Rewards.Table(), dao.Rewards.Columns().Id, dao.TaskRewards.Table(), dao.TaskRewards.Columns().RewardId)). LeftJoin(dao.RewardTypes.Table(), fmt.Sprintf("`%s`.`%s` = `%s`.`%s`", dao.RewardTypes.Table(), dao.RewardTypes.Columns().Id, dao.Rewards.Table(), dao.Rewards.Columns().RewardTypeId)). Fields( fmt.Sprintf("%s.*, `%s`.`%s` AS %s", dao.Rewards.Table(), dao.RewardTypes.Table(), dao.RewardTypes.Columns().Name, "reward_type_name", ), ).Where(dao.TaskRewards.Columns().TaskId, task.TaskID).Scan(&result.TaskList[i].Reward) if err != nil { return nil, err } //任务状态=1或者2不做操作,其他查询门店奖励是否全部领取 if task.Status != 1 && task.Status != 2 { count, err := dao.UserTasks.Ctx(ctx).Where(dao.UserTasks.Columns().TaskId, task.TaskID).Where(dao.UserTasks.Columns().UserId, in.UserId).LeftJoin(dao.UserTaskRewards.Table(), fmt.Sprintf("%s.user_tasks_id = %s.id", dao.UserTaskRewards.Table(), dao.UserTasks.Table())).LeftJoin(dao.Rewards.Table(), fmt.Sprintf("%s.id = %s.reward_id", dao.Rewards.Table(), dao.UserTaskRewards.Table())).Where(dao.Rewards.Columns().Source, 2).Where(dao.UserTaskRewards.Columns().Status, 2).Count() if err != nil { return nil, ecode.Fail.Sub("查询用户门店任务奖励失败") } if count > 0 { tasks[i].Status = 2 } else { tasks[i].Status = 3 } } //else { // data.Status = task.Status //} //tasks = append(tasks, data) // 根据用户完成次数和任务指标次数判任务是否完成,修改任务记录状态为 3 if int(task.UserTimes) >= task.TargetTimes { _, err := dao.UserTasks.Ctx(ctx).Where(do.UserTasks{TaskId: task.TaskID}).Where(do.UserTasks{UserId: in.UserId}).Data(do.UserTasks{Status: 3}).Update() if err != nil { return nil, ecode.Fail.Sub("更新用户任务记录状态异常") } } } data = result.TaskList return &model.GetTaskListV2Out{ Data: data, PageIdx: pageIdx, }, nil } } func (s *sTask) SyncTaskFromGamelife(ctx context.Context) (out *model.SyncTaskOut, err error) { stores, err := dao.Stores.Ctx(ctx).Fields(dao.Stores.Columns().Id, dao.Stores.Columns().NetbarAccount).All() if err != nil { return nil, err } games, err := dao.Games.Ctx(ctx).Fields(dao.Games.Columns().GameName, dao.Games.Columns().GameId).All() if err != nil { return nil, err } var wg sync.WaitGroup for _, store := range stores { store := store // 捕获循环变量 wg.Add(1) go func() { defer wg.Done() for _, game := range games { activity, err := gamelife.GetGamelifeClient(ctx).RequestActivity( ctx, &model.QQNetbarActivityIn{ ServiceName: consts.GetNonLoginTaskList, TaskParam: model.TaskParam{ Gid: game["game_id"].Int(), NetBarAccount: store["netbar_account"].String(), Num: 50, Pageidx: "", }, }, ) if err != nil { glog.Errorf(ctx, "获取任务失败,网吧=%s,游戏=%s,错误=%v", store["netbar_account"].String(), game["game_name"].String(), err) continue } result, ok := activity.(*model.GameTaskResponse) if !ok { glog.Errorf(ctx, "数据类型转换失败,网吧=%s,游戏=%s", store["netbar_account"].String(), game["game_name"].String()) continue } var insertCount, skipCount int for _, task := range result.TaskList { exist, err := dao.Tasks.Ctx(ctx). Where("task_id = ? AND store_id = ? AND game_id = ?", task.TaskID, store["id"].Int(), game["game_id"].Int()). Count() if err != nil { glog.Errorf(ctx, "检查任务是否存在失败,task_id=%s,网吧=%s,游戏=%s,错误=%v", task.TaskID, store["netbar_account"].String(), game["game_name"].String(), err) continue } if exist > 0 { skipCount++ continue } taskMap := gconv.Map(task) delete(taskMap, "PrizeList") delete(taskMap, "prize_list") delete(taskMap, "reward") _, err = dao.Tasks.Ctx(ctx).Data(do.Tasks{ TaskId: task.TaskID, StoreId: store["id"].Int(), GameId: game["game_id"].Int(), NetbarAcconut: store["netbar_account"].String(), Task: gconv.Bytes(taskMap), }).Insert() if err != nil { glog.Errorf(ctx, "插入任务失败,task_id=%s,网吧=%s,游戏=%s,错误=%v", task.TaskID, store["netbar_account"].String(), game["game_name"].String(), err) continue } insertCount++ } glog.Infof(ctx, "任务同步完成,网吧=%s,游戏=%s,插入任务=%d,跳过任务=%d", store["netbar_account"].String(), game["game_name"].String(), insertCount, skipCount) } }() } wg.Wait() return }