package services import ( "context" "errors" "eta/eta_task/models" "eta/eta_task/utils" "fmt" "github.com/beego/beego/v2/task" "strconv" "strings" "time" ) // EdbTaskNameMap 手工指标定时任务名称map集合 var EdbTaskNameMap map[string]map[string]bool // EdbTaskNameChannel 手工指标定时任务名称channel var EdbTaskNameChannel chan string // EdbTaskStopChannel 手工指标定时任务停止channel var EdbTaskStopChannel chan string // EdbTaskRunNum 手工指标定时任务开始次数 var EdbTaskRunNum int // AddEdbTask 新增手工指标数据录入提醒 func AddEdbTask(cont context.Context) (err error) { //失败列表 failList := make([]string, 0) defer func() { if len(failList) > 0 { fmt.Println("提醒失败:") for _, v := range failList { fmt.Println(v) } } }() list, err := models.GetEdbInfoByFrequencyNotDay() if err != nil { fmt.Println("查询获取频度非日度 且 提醒时间不为空 的指标数据失败,Err:", err.Error()) } //如果还没有初始化map,那么先初始 if EdbTaskNameMap == nil { EdbTaskNameMap = make(map[string]map[string]bool) } tmpEdbTaskNameMap := make(map[string]bool) // 今天的日期字符串(格式:2021-10-25) todayStr := time.Now().Format(utils.FormatDate) //当前周的周一与周日 nowWeekFirstDay := utils.GetNowWeekMonday() nowWeekLastDay := utils.GetNowWeekLastDay() //当前月的一号与最后一天 nowMonthFirstDay := utils.GetNowMonthFirstDay() nowMonthLastDay := utils.GetNowMonthLastDay() //当前季度的第一天与最后一天 nowQuarterFirstDay := utils.GetNowQuarterFirstDay() nowQuarterLastDay := utils.GetNowQuarterLastDay() //当前半年的第一天与最后一天 nowHalfYearFirstDay := utils.GetNowHalfYearFirstDay() nowHalfYearLastDay := utils.GetNowHalfYearLastDay() // 当前年的第一天与最后一天 nowYearFirstDay := utils.GetNowYearFirstDay() nowYearLastDay := utils.GetNowYearLastDay() debugNoticeUserId := 0 //测试环境,需要发送消息的用户 //测试环境也不发了 //if utils.RunMode == "debug" { // tmpWxUser, tmpErr := models.GetWxUserByMobile("17634786714") // if tmpErr == nil && tmpWxUser != nil { // //debugNoticeUserId = 44078 //测试环境的话,发送邮箱给颜鹏 // debugNoticeUserId = int(tmpWxUser.UserId) //测试环境的话,发送邮箱给嘉豪 // } //} //task.globalTaskManager.adminTaskList for _, edb := range list { if edb.UserId <= 0 { continue //没有配置user_id的话,那么不需要提醒 } tmpEdb := edb //指标信息 isNotice := false //是否需要提醒 noticeTime := "12:00:00" //提醒时间 var dataDtTime time.Time edbData, tmpErr := models.GetLastEdbdataInfo(tmpEdb.TradeCode) if tmpErr != nil { if tmpErr.Error() != utils.ErrNoRow() { failList = append(failList, fmt.Sprint(tmpEdb.TradeCode, "失败,Err:", tmpErr.Error())) continue } } //如果确实是有数据的 if edbData != nil { tmpDataDtTime, _ := time.ParseInLocation(utils.FormatDate, edbData.Dt, time.Now().Location()) dataDtTime = tmpDataDtTime } switch tmpEdb.Frequency { case "周度": modifyDate := nowWeekLastDay //下次更新日期 if tmpEdb.NoticeTime != "" { addDay := 7 noticeArr := strings.Split(tmpEdb.NoticeTime, " ") if len(noticeArr) >= 2 { noticeTime = noticeArr[1] } noticeWeek := noticeArr[0] switch noticeWeek { case "周一": addDay = 1 case "周二": addDay = 2 case "周三": addDay = 3 case "周四": addDay = 4 case "周五": addDay = 5 case "周六": addDay = 6 case "周日": addDay = 7 } modifyDate = modifyDate.AddDate(0, 0, addDay-7) } //如果正好是提醒日,同时本周没有过记录,那么需要提醒 if todayStr == modifyDate.Format(utils.FormatDate) && !nowWeekFirstDay.Before(dataDtTime) { isNotice = true } case "月度": addDay := 0 modifyDate := nowMonthLastDay //下次更新日期 if tmpEdb.NoticeTime != "" { strArr := strings.Split(tmpEdb.NoticeTime, "日") if len(strArr) >= 2 { noticeTime = strArr[1] } tmpAddDay, tmpErr := strconv.Atoi(strArr[0]) if tmpErr != nil { continue } addDay = tmpAddDay - 1 modifyDate = nowMonthFirstDay.AddDate(0, 0, addDay) } //如果正好是提醒日,同时本月没有过记录,那么需要提醒 if todayStr == modifyDate.Format(utils.FormatDate) && !nowMonthFirstDay.Before(dataDtTime) { isNotice = true } case "季度": //提醒时间 if tmpEdb.NoticeTime != "" { noticeArr := strings.Split(tmpEdb.NoticeTime, " ") if len(noticeArr) >= 2 { noticeTime = noticeArr[1] } } //每季度更新数据时间 //如果正好是提醒日(每季度最后一天),同时本季度没有过记录,那么需要提醒 if todayStr == nowQuarterLastDay.Format(utils.FormatDate) && !nowQuarterFirstDay.Before(dataDtTime) { isNotice = true } case "半年度": //提醒时间 if tmpEdb.NoticeTime != "" { noticeArr := strings.Split(tmpEdb.NoticeTime, " ") if len(noticeArr) >= 2 { noticeTime = noticeArr[1] } } //每半年度更新数据时间 //如果正好是提醒日(每半年度最后一天),同时本半年度没有过记录,那么需要提醒 if todayStr == nowHalfYearLastDay.Format(utils.FormatDate) && !nowHalfYearFirstDay.Before(dataDtTime) { isNotice = true } case "年度": //提醒时间 if tmpEdb.NoticeTime != "" { noticeArr := strings.Split(tmpEdb.NoticeTime, " ") if len(noticeArr) >= 2 { noticeTime = noticeArr[1] } } //每年度更新数据时间 //如果正好是提醒日(每年度最后一天),同时半年度没有过记录,那么需要提醒 if todayStr == nowYearLastDay.Format(utils.FormatDate) && !nowYearFirstDay.Before(dataDtTime) { isNotice = true } } if isNotice { taskName := "edb_task_" + todayStr + ":" + fmt.Sprint(tmpEdb.TradeCode) //fmt.Println(taskName, ";", tmpEdb.SecName) //定时任务 tmpTaskFunc := func(ctx context.Context) (funcErr error) { //方法执行结束后,移除定时任务 defer func() { EdbTaskNameChannel <- taskName }() // 匿名方法内判断是否发送提醒,因为可能时间到的时候,发现 funcIsNotice := false // 再次获取指标数据详情 edbData, tmpErr := models.GetLastEdbdataInfo(tmpEdb.TradeCode) if tmpErr != nil { if tmpErr.Error() != utils.ErrNoRow() { funcErr = tmpErr return } } if utils.RunMode == "debug" && debugNoticeUserId > 0 { tmpEdb.UserId = debugNoticeUserId //测试环境的话,发送邮箱给嘉豪 } //数据过期时间 var funcDataDtTime time.Time //如果确实是有数据的 if edbData != nil { tmpDataDtTime, _ := time.ParseInLocation(utils.FormatDate, edbData.Dt, time.Now().Location()) funcDataDtTime = tmpDataDtTime } //提示频度文案 notifyFrequency := "每日" switch tmpEdb.Frequency { case "周度": notifyFrequency = "每周" modifyDate := nowWeekLastDay //下次更新日期 if tmpEdb.NoticeTime != "" { addDay := 7 noticeArr := strings.Split(tmpEdb.NoticeTime, " ") if len(noticeArr) >= 2 { noticeTime = noticeArr[1] } noticeWeek := noticeArr[0] switch noticeWeek { case "周一": addDay = 1 case "周二": addDay = 2 case "周三": addDay = 3 case "周四": addDay = 4 case "周五": addDay = 5 case "周六": addDay = 6 case "周日": addDay = 7 } modifyDate = modifyDate.AddDate(0, 0, addDay-7) } //如果正好是提醒日,同时本周没有过记录,那么需要提醒 if todayStr == modifyDate.Format(utils.FormatDate) && !nowWeekFirstDay.Before(funcDataDtTime) { funcIsNotice = true } case "月度": notifyFrequency = "每月" addDay := 0 modifyDate := nowMonthLastDay //下次更新日期 if tmpEdb.NoticeTime != "" { strArr := strings.Split(tmpEdb.NoticeTime, "日") if len(strArr) >= 2 { noticeTime = strArr[1] } tmpAddDay, tmpErr := strconv.Atoi(strArr[0]) if tmpErr != nil { funcErr = tmpErr } addDay = tmpAddDay - 1 modifyDate = nowMonthFirstDay.AddDate(0, 0, addDay) } //如果正好是提醒日,同时本月没有过记录,那么需要提醒 if todayStr == modifyDate.Format(utils.FormatDate) && !nowMonthFirstDay.Before(funcDataDtTime) { funcIsNotice = true } case "季度": notifyFrequency = "每季度" //提醒时间 if tmpEdb.NoticeTime != "" { noticeArr := strings.Split(tmpEdb.NoticeTime, " ") if len(noticeArr) >= 2 { noticeTime = noticeArr[1] } } //每季度更新数据时间 //如果正好是提醒日(每季度最后一天),同时本季度没有过记录,那么需要提醒 if todayStr == nowQuarterLastDay.Format(utils.FormatDate) && !nowQuarterFirstDay.Before(funcDataDtTime) { funcIsNotice = true } case "半年度": notifyFrequency = "每半年度" //提醒时间 if tmpEdb.NoticeTime != "" { noticeArr := strings.Split(tmpEdb.NoticeTime, " ") if len(noticeArr) >= 2 { noticeTime = noticeArr[1] } } //每半年度更新数据时间 //如果正好是提醒日(每半年度最后一天),同时本半年度没有过记录,那么需要提醒 if todayStr == nowHalfYearLastDay.Format(utils.FormatDate) && !nowHalfYearFirstDay.Before(funcDataDtTime) { funcIsNotice = true } case "年度": notifyFrequency = "每年" //提醒时间 if tmpEdb.NoticeTime != "" { noticeArr := strings.Split(tmpEdb.NoticeTime, " ") if len(noticeArr) >= 2 { noticeTime = noticeArr[1] } } //每年度更新数据时间 //如果正好是提醒日(每年度最后一天),同时半年度没有过记录,那么需要提醒 if todayStr == nowYearLastDay.Format(utils.FormatDate) && !nowYearFirstDay.Before(funcDataDtTime) { funcIsNotice = true } } //fmt.Println(tmpEdb.TradeCode, " funcIsNotice:", funcIsNotice) //如果还是要提醒 if funcIsNotice { //用户微信openid列表数据 openIdList := make([]*models.OpenIdList, 0) //获取用户信息 admin, err := models.GetAdminByAdminId(tmpEdb.UserId) if err != nil { if err.Error() == utils.ErrNoRow() { funcErr = errors.New("openId 列表为空" + strconv.Itoa(tmpEdb.UserId)) return } else { return err } } if admin == nil { funcErr = errors.New("openId 列表为空" + strconv.Itoa(tmpEdb.UserId)) return } //发送消息 if admin.OpenId == "" { funcErr = errors.New("openId 列表为空" + strconv.Itoa(tmpEdb.UserId)) return } openIdTemp := new(models.OpenIdList) openIdTemp.OpenId = admin.OpenId openIdList = append(openIdList, openIdTemp) first := "数据录入提醒" keyword1 := tmpEdb.SecName + "该更新了" keyword2 := notifyFrequency + " " + tmpEdb.NoticeTime remark := tmpEdb.SecName + "该更新了" err = SendWxMsgWithFrequency(first, keyword1, keyword2, remark, openIdList) if err != nil { return err } //发送成功,记录发送日志 { sendRecord := new(models.EdbinfoSendMsgRecord) sendRecord.UserId = tmpEdb.UserId sendRecord.TradeCode = tmpEdb.TradeCode sendRecord.CreateTime = time.Now() err = models.AddEdbinfoSendMsgRecord(sendRecord) if err != nil { return err } } } return } //添加定时任务(没有设置通知时间就不进行定时任务通知了) spec := `` if noticeTime != "" { noticeArr := strings.Split(noticeTime, ":") if len(noticeArr) == 3 { //spec = ` */20 * * * * * ` spec = fmt.Sprintf(` %s %s %s * * * `, noticeArr[2], noticeArr[1], noticeArr[0]) //定时任务开始的时间 tmpTask := task.NewTask(taskName, spec, tmpTaskFunc) task.AddTask(taskName, tmpTask) tmpEdbTaskNameMap[taskName] = true } } } } //将当天的手工指标加入到手工指标池去 EdbTaskNameMap[todayStr] = tmpEdbTaskNameMap //开启协程,用来清除定时任务 go deleteTask() //如果当前定时任务执行次数大于0次,那么需要往手工指标定时任务停止channel写入数据,用来关闭昨天没有执行的的定时任务 if EdbTaskRunNum > 0 { //清除昨天的数据 EdbTaskStopChannel <- time.Now().AddDate(0, 0, -1).Format(utils.FormatDate) } //手工指标定时任务开始次数累加 EdbTaskRunNum++ return //fmt.Println(task.NewMapSorter()) } // deleteTask 清除已通知的任务 func deleteTask() { for { select { case taskName := <-EdbTaskNameChannel: task.DeleteTask(taskName) delete(EdbTaskNameMap, taskName) case dayStr := <-EdbTaskStopChannel: //收到停止信号,先清除掉那一天的定时任务, for taskName := range EdbTaskNameMap[dayStr] { task.DeleteTask(taskName) delete(EdbTaskNameMap, taskName) } break } } }