package task import ( "app.yhyue.com/moapp/jybase/common" "app.yhyue.com/moapp/jybase/date" "app.yhyue.com/moapp/jybase/go-logger/logger" "app.yhyue.com/moapp/jybase/redis" "app.yhyue.com/moapp/message/config" "app.yhyue.com/moapp/message/db" "app.yhyue.com/moapp/message/handler/activity" "context" "encoding/json" "fmt" "github.com/gogf/gf/v2/os/gcfg" "github.com/gogf/gf/v2/os/gcron" "github.com/gogf/gf/v2/os/gctx" "github.com/gogf/gf/v2/os/gtime" "strings" "time" ) const ( TableWinnerInfo2210 = "winner_info_22_10" Mold1 = "1" // 中奖类型 1:小米智能音响 Mold2 = "2" // 中奖类型 2:ipad ActivityMode1 = 1 // 双十一 ActivityMode2 = 2 // 双十二 ) var ( flag = false // 是否已经查询到 monitorConfig config.OrderMonitorConfig ruleWinNumFlag []map[int]struct{} ) func init() { // 获取配置信息 monitorConfig = config.OrderMonitorConfig{ DateSpecial: date.FormatDate(>ime.NewFromStrLayout(gcfg.Instance().MustGet(gctx.New(), "orderMonitor.dateSpecial").String(), "2006-01-02T15:04:05Z").Time, date.Date_Short_Layout), OpenCron: gcfg.Instance().MustGet(gctx.New(), "orderMonitor.openCron").String(), SelectCron: gcfg.Instance().MustGet(gctx.New(), "orderMonitor.selectCron").String(), WinNumberDaily: gcfg.Instance().MustGet(gctx.New(), "orderMonitor.winNumberDaily").Int(), WinNumbersSpecial: gcfg.Instance().MustGet(gctx.New(), "orderMonitor.winNumbersSpecial").Int(), Switch: gcfg.Instance().MustGet(gctx.New(), "orderMonitor.switch").Bool(), ActivityMode: gcfg.Instance().MustGet(gctx.New(), "orderMonitor.activityMode").Int(), } rules, _ := gcfg.Instance().MustGet(gctx.New(), "orderMonitor.rules").MarshalJSON() err := json.Unmarshal(rules, &monitorConfig.Rules) if err != nil { panic("加载活动规则配置失败") } } // SelectOrderTask 订单监控 func SelectOrderTask() { if !monitorConfig.Switch { logger.Info("订单监控开关未打开,不再启动定时任务") return } // 活动已结束 不再启动定时任务 if time.Now().After(activity.MembershipDay.Ed) { logger.Info("活动时间已结束,不再启动定时任务") return } var ( err error ctx = gctx.New() ) // 订单查询任务 switch monitorConfig.ActivityMode { case ActivityMode1: // 双十一活动的模式 每天的第多少名 _, err = gcron.Add(ctx, monitorConfig.SelectCron, monitor, "selectJob") logger.Info("add selectJob 1") case ActivityMode2: // 活动期间的第多少名 // 初始化待查询的获奖顺序 for i := 0; i < len(monitorConfig.Rules); i++ { rule := monitorConfig.Rules[i] tmp := map[int]struct{}{} for j := 0; j < len(rule.WinNum); j++ { tmp[rule.WinNum[j]] = struct{}{} } ruleWinNumFlag = append(ruleWinNumFlag, tmp) } logger.Info("初始化待查询的获奖顺序到内存") _, err = gcron.Add(ctx, monitorConfig.SelectCron, monitorMode2, "selectJob") logger.Info("add selectJob 2") } if err != nil { logger.Error("定时任务selectJob添加失败", err) return } if time.Now().Before(activity.MembershipDay.T2) { // 活动未开始 gcron.Stop("selectJob") // 停掉订单查询任务 等后边的定时任务开启 logger.Info("活动还未开始,暂停查询任务 selectJob stop") } // 开启定时开启任务 _, err = gcron.Add(ctx, monitorConfig.OpenCron, func(ctx context.Context) { now := time.Now() if now.After(activity.MembershipDay.Ed) { // 活动已结束 移除掉任务 logger.Info("活动结束,移除任务") gcron.Remove("openCronJob") gcron.Remove("selectJob") return } // 活动时间范围内 开启订单查询的定时任务 _, inTime, _ := activity.MembershipDay.InActivity() if inTime { if gcron.Search("selectJob").Status() == gcron.StatusStopped { flag = false // 重置 gcron.Start("selectJob") logger.Info("开启 selectJob 任务") } } }, "openCronJob") if err != nil { logger.Error("定时任务openCronJob失败", err) } logger.Info("openCronJob 启动成功") } // 订单监控 双十一 查询活动期间的每天的第多少名 func monitor(ctx context.Context) { logger.Info("开始本轮订单查询") _, inTime, _ := activity.MembershipDay.InActivity() if inTime { // 如果需要查第111个 日期范围内 特殊日期 if date.NowFormat(date.Date_Short_Layout) == monitorConfig.DateSpecial { logger.Info(fmt.Sprintf("开始查询第%v个人员", monitorConfig.WinNumbersSpecial)) rs111 := selectOrder(monitorConfig.WinNumbersSpecial) if rs111 != nil { logger.Info(fmt.Sprintf("查询到第%v个人员", monitorConfig.WinNumbersSpecial)) saveData := map[string]interface{}{ "phone": rs111["user_phone"], "userid": rs111["user_id"], "winnerdate": rs111["pay_time"], "mold": Mold2, "createdate": date.NowFormat(date.Date_Full_Layout), } if existWinnerInfo() { logger.Info("当日已存在中奖信息") flag = true } else { if saveWinnerInfo(saveData) { flag = true logger.Info("中奖信息保存成功:", saveData) } else { logger.Error("中奖信息保存失败:", saveData) } } } } else { rs := selectOrder(monitorConfig.WinNumberDaily) if rs != nil { // 查到了 logger.Info(fmt.Sprintf("查询到第%d个人员", monitorConfig.WinNumberDaily)) data := map[string]interface{}{ "phone": rs["user_phone"], "userid": rs["user_id"], "winnerdate": rs["pay_time"], "mold": Mold1, "createdate": date.NowFormat(date.Date_Full_Layout), } if existWinnerInfo() { logger.Info("当日已存在中奖信息") flag = true } else { if saveWinnerInfo(data) { flag = true logger.Info("中奖信息保存成功:", data) } else { logger.Error("中奖信息保存失败:", data) } } } } if flag { logger.Info("今日已查询到 暂停任务") gcron.Stop("selectJob") logger.Info("selectJob stop") } } } // 双十二活动 查询活动期间的第多少名 func monitorMode2(ctx context.Context) { logger.Info("开始本轮订单查询") if time.Now().Before(activity.MembershipDay.T2) { // 活动未开始 logger.Info("当前时间不在活动时间范围内") return } needSelect := false // 任务是否需要继续 // 遍历活动抽奖规则 for i := 0; i < len(monitorConfig.Rules); i++ { rules := monitorConfig.Rules[i] if len(ruleWinNumFlag[i]) == 0 { // 没有需要查询的中奖顺序 continue } // 遍历中奖顺序 for _, num := range rules.WinNum { if _, ok := ruleWinNumFlag[i][num]; !ok { // 不在待查询的map中 continue } rs := selectOrder2(num, rules.Products, rules.PriceLimit, rules.PriceStart, rules.PriceEnd, date.FormatDate(&activity.MembershipDay.T2, date.Date_Full_Layout), date.FormatDate(&activity.MembershipDay.Ed, date.Date_Full_Layout)) if len(rs) == 0 { break // 如果没有查询到 等待下一轮任务再查询 } logger.Info(num, "查到") data := map[string]interface{}{ "phone": rs["user_phone"], "userid": rs["user_id"], "winnerdate": rs["pay_time"], "mold": rules.Mold, "createdate": date.NowFormat(date.Date_Full_Layout), "ordercode": rs["order_code"], } if existOrderWinnerInfo(common.ObjToString(rs["order_code"])) { // 从待查找的key中删除 delete(ruleWinNumFlag[i], num) logger.Info("该订单中奖信息重复保存", data) } else { // 存库 if saveWinnerInfo(data) { logger.Info("保存成功", data) delete(ruleWinNumFlag[i], num) // 从待查找的key中删除 } else { logger.Info("保存失败", data) } } } if len(ruleWinNumFlag[i]) > 0 { logger.Info(ruleWinNumFlag[i]) needSelect = true // 存在未查询到的 定时任务不用关闭 } } if time.Now().After(activity.MembershipDay.Ed) { // 活动已结束 logger.Info("活动已结束") needSelect = false } if !needSelect { // 不用再找了 结束任务 gcron.Remove("selectJob") gcron.Remove("openCronJob") logger.Info("结束了") } } // 查订单表 func selectOrder(num int) map[string]interface{} { sql := `SELECT order_code, user_phone, user_id, pay_time FROM dataexport_order WHERE order_status = 1 and product_type IN ( "VIP订阅", "大会员", "数据流量包" ) AND is_backstage_order = 0 and pay_time is not null AND TO_DAYS(pay_time) = to_days(now()) ORDER BY pay_time LIMIT ?,1 ` rs := db.Mysql.SelectBySql(sql, num-1) if rs != nil && len(*rs) == 1 { return (*rs)[0] } logger.Info("未查到", rs) return nil } // 查询活动期间指定支付顺序的订单 func selectOrder2(num int, productType []string, priceLimit bool, priceStart, priceEnd int, startTime, endTime string) map[string]interface{} { var products []string var values []interface{} productTypeStr := "" // 产品类型 priceLimitStr := "" // 价格限制 values = append(values, startTime, endTime) // 拼接产品类型 if len(productType) > 0 { for i := 0; i < len(productType); i++ { products = append(products, "?") values = append(values, productType[i]) } productTypeStr = fmt.Sprintf(" and product_type IN (%s) ", strings.Join(products, ",")) } // 拼接价格限制 if priceLimit { if priceStart != 0 { priceLimitStr = " and pay_money>=? " values = append(values, priceStart) } if priceEnd != 0 { priceLimitStr += " and pay_money<=? " values = append(values, priceEnd) } } values = append(values, num-1) sql := `SELECT order_code, user_phone, user_id, pay_time FROM dataexport_order WHERE order_status = 1 and pay_time >=? and pay_time 0 } // 当天是否已经保存过中奖信息 func existWinnerInfo() bool { logger.Info("select winner info ") return db.Mysql.CountBySql("SELECT count(id) as count FROM jianyu.winner_info_22_10 where TO_DAYS(createdate) = TO_DAYS(NOW());") > 0 } // 中奖订单号是否已经保存过 func existOrderWinnerInfo(orderCode string) bool { logger.Info("select order winner info ") return db.Mysql.CountBySql("SELECT count(id) as count FROM jianyu.winner_info_22_10 where ordercode = ?", orderCode) > 0 }