diff --git a/go.mod b/go.mod index 3b786315a1e3d27f57c24523e63c0bf632757368..892bc61659649177ff03759098b6ebb4d4b429eb 100644 --- a/go.mod +++ b/go.mod @@ -26,6 +26,7 @@ require ( github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.66.0 github.com/prometheus/alertmanager v0.25.0 github.com/robfig/cron v1.2.0 + github.com/robfig/cron/v3 v3.0.1 github.com/satori/go.uuid v1.2.0 github.com/spf13/cast v1.5.0 github.com/spf13/pflag v1.0.5 diff --git a/go.sum b/go.sum index a9442f9d720866056996470eb9cbdbf81cba9de7..fc8a3b91fa2892767e9f65e12e6051a3116313a3 100644 --- a/go.sum +++ b/go.sum @@ -579,6 +579,8 @@ github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6O github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/robfig/cron v1.2.0 h1:ZjScXvvxeQ63Dbyxy76Fj3AT3Ut0aKsyd2/tl3DTMuQ= github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k= +github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= +github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= diff --git a/src/bean/entity/work_order.go b/src/bean/entity/work_order.go index a99928366d47797f959e5550c0cfea06fbc83b79..50c68df0a7c2394931f8a32639089d4a9d32cec4 100644 --- a/src/bean/entity/work_order.go +++ b/src/bean/entity/work_order.go @@ -1,6 +1,8 @@ package entity -import "time" +import ( + "time" +) type WorkOrder struct { Id int `json:"id" xorm:"pk autoincr" ` // id diff --git a/src/main.go b/src/main.go index 752dd2198ca603da03ec0eeccabdaf722e5ef075..0ce4306a36e71dd1b1c8c6f04e23af7ef2287d66 100644 --- a/src/main.go +++ b/src/main.go @@ -53,7 +53,7 @@ func main() { //启动定时任务 cron.StartCron() - service.PushWorkOrderMessage() + service.CronPushWorkOrder() // server start... conf.Logger.Info("config info", zap.Any("options", conf.Options)) conf.Logger.Error("server start err", zap.Error(newServer().ListenAndServe())) @@ -151,12 +151,6 @@ func initAnsibleHosts() { if err != nil { fmt.Println(err.Error()) } - //else { - // _, err := f.Write([]byte("[web]\n")) - // if err != nil { - // fmt.Println(err.Error()) - // } - //} } func initTempDirPrefix() { @@ -181,14 +175,4 @@ func initAnsibleSSH() { fmt.Println(err.Error()) } } - //f2, err := os.CreateIndex("/root/.ssh/id_rsa.pub") - //defer f2.Close() - //if err != nil { - // fmt.Println(err.Error()) - //} else { - // _, err := f.Write([]byte(conf.Options.PublicKeySSH)) - // if err != nil { - // fmt.Println(err.Error()) - // } - //} } diff --git a/src/pkg/beagle/constant/constant.go b/src/pkg/beagle/constant/constant.go index 7a5eba7ccc44d31c95619f00ad498f59bac882da..308251d997b09206525226cee77d415a3c728053 100644 --- a/src/pkg/beagle/constant/constant.go +++ b/src/pkg/beagle/constant/constant.go @@ -175,3 +175,10 @@ func DisposedStatusText(code int) string { return "未知状态" } } + +// 工单定时类型 +const ( + TimingClick = 1 //手动下发 + TimingWeekly = 2 //按周 + TimingCustom = 3 //自定义时间 +) diff --git a/src/router/workorderrouter.go b/src/router/workorderrouter.go index 64392eac8d5704b6c037d879bea6757c9d12bb0e..d5ef968a9913616672caf043fb1cce0f2cb8cb61 100644 --- a/src/router/workorderrouter.go +++ b/src/router/workorderrouter.go @@ -46,5 +46,4 @@ func InitWorkOrderRouter(e *gin.Engine) { me.PUT("/feedback", controller.FeedbackWorkOrderMe) // 处置反馈 me.GET("/list", controller.ListWorkOrderMe) // 我的业务工单列表 } - //so.POST("/note_sg", controller.WorkOrderPushNoteMsg) } diff --git a/src/service/cron/common.go b/src/service/cron/common.go index d5acf394717d8f198e26f057bc059558d8fb85c9..10e8b1a0ab9bd2bf8d4f106b63a6b75570323b39 100644 --- a/src/service/cron/common.go +++ b/src/service/cron/common.go @@ -10,6 +10,4 @@ func StartCron() { defer c.Start() c.AddFunc("0 0 0 * * *", service.CronStatusDetection) // 每天凌晨0点状态检测 - - c.AddFunc("0 0 0 * * *", service.CronWorkOrderIssuance) // 每天凌晨0点扫描当天需下发工单 } diff --git a/src/service/work_order.go b/src/service/work_order.go index dc2d60e2b946f75aebf26ae9b7865c42266d89e5..44cc172c7bae601204c3d4fb114cf844041dd7af 100644 --- a/src/service/work_order.go +++ b/src/service/work_order.go @@ -5,14 +5,17 @@ import ( "fmt" "github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi" json "github.com/json-iterator/go" + "github.com/robfig/cron/v3" "github.com/wanghuiyt/ding" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/entity" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/vo/request" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/vo/response" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/common/client" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/common/conf" + "gitlab.wodcloud.com/smart-operation/so-operation-api/src/pkg/beagle/constant" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/pkg/beagle/jsontime" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/pkg/beagle/resp" + "gitlab.wodcloud.com/smart-operation/so-operation-api/src/util" "go.uber.org/zap" "strings" "time" @@ -165,6 +168,11 @@ func (w *WorkOrderManageSvc) StateWorkOrderManage(req request.StateWorkOrderReq) err = resp.DbUpdateError.WithError(err) return } + + if req.TimingState == 1 { + //创建定时任务 + CronPushWorkOrder() + } return } @@ -715,194 +723,140 @@ func WorkOrderPushNoteMsg(orderName string, phone []string, orderLevel int) (err return } -// CronWorkOrderIssuance 定时任务-每天凌晨0点检测当天需下发工单 -func CronWorkOrderIssuance() { +// PushObjMsg 解析用户并推送消息 +func PushObjMsg(obj, orderName string, orderLevel int) (err error) { + var pushObj request.PushObj + err = json.Unmarshal([]byte(obj), &pushObj) + if err != nil { + return + } + + var phones []string + for _, v := range pushObj.UserObj { + phones = append(phones, v.Phone) + } + switch pushObj.PushMethod { + case 1: + //发送钉钉消息 + err = WorkOrderPushDingTalkMsg(orderName, orderLevel, phones) + if err != nil { + return + } + case 2: + //发送短信 + err = WorkOrderPushNoteMsg(orderName, phones, orderLevel) + if err != nil { + return + } + case 3: + //发送钉钉消息 + err = WorkOrderPushDingTalkMsg(orderName, orderLevel, phones) + if err != nil { + return + } + //发送短信 + err = WorkOrderPushNoteMsg(orderName, phones, orderLevel) + if err != nil { + return + } + } + conf.Logger.Info("定时下发工单完成,工单名称:" + orderName) + return +} + +var c = cron.New(cron.WithSeconds()) + +// CronPushWorkOrder 创建工单下发定时任务 +func CronPushWorkOrder() { db, err := client.GetDbClient() if err != nil { - fmt.Println("CronStatusDetection err:", err.Error()) + conf.Logger.Error("获取数据库连接", zap.Error(err)) return } //查询推送工单 workOrderList := make([]entity.WorkOrder, 0) - finder := db.Table("work_order_manage").Where("timing_state = 1 AND (timing_type = 2 OR timing_type = 3)") + finder := db.Table("work_order_manage").Where("timing_state = ? AND (timing_type = ? "+ + "OR timing_type = ?)", constant.TimingClick, constant.TimingWeekly, constant.TimingCustom) err = finder.Find(&workOrderList) if err != nil { - fmt.Println("CronStatusDetection err:", err.Error()) + conf.Logger.Error("查询推送工单", zap.Error(err)) return } - week := map[time.Weekday]int{ - time.Monday: 1, - time.Tuesday: 2, - time.Wednesday: 3, - time.Thursday: 4, - time.Friday: 5, - time.Saturday: 6, - time.Sunday: 7, - } - + c.Stop() + defer c.Start() for _, v := range workOrderList { - if v.TimingType == 2 { - //按周 + var pushObj request.PushObj + err = json.Unmarshal([]byte(v.PushObj), &pushObj) + if err != nil { + return + } + svc := WorkOrderManageSvc{User: entity.SystemUserInfo{SystemAccount: v.CreateUser}} + + if v.TimingType == constant.TimingWeekly { var timingWeekly request.TimingWeekly err = json.Unmarshal([]byte(v.TimingRule), &timingWeekly) if err != nil { - fmt.Println("CronStatusDetection err:", err.Error()) + conf.Logger.Error("反序列化定时规则", zap.Error(err)) continue } - days := week[time.Now().Weekday()] - for _, i := range timingWeekly.Week { - if i == days { - //写redis - err = PushRedisWorkOrder(timingWeekly.PointTime, v.PushObj, v.OrderName, v.OrderLevel) - if err != nil { - fmt.Println("CronStatusDetection redis set err:", err.Error()) - continue - } - break + + for k, v1 := range timingWeekly.Week { + if v1 == 7 { + timingWeekly.Week[k] = 0 } } - } else if v.TimingType == 3 { - //自定义时间 - var timingCustom []request.TimingCustom - err = json.Unmarshal([]byte(v.TimingRule), &timingCustom) + t, err := time.Parse(jsontime.LocalTimeFormat, timingWeekly.PointTime) if err != nil { - fmt.Println("CronStatusDetection json Unmarshal err:", err.Error()) + conf.Logger.Error("时间点类型转换错误", zap.Error(err)) continue } - for _, v1 := range timingCustom { - t := time.Now() - dateFrom, err1 := time.Parse(jsontime.LocalDateFormat, v1.DateFrom) - if err1 != nil { - fmt.Println("CronStatusDetection dateFrom parse err:", err1.Error()) - continue - } - dateTo, err1 := time.Parse(jsontime.LocalDateFormat, v1.DateTo) - if err1 != nil { - fmt.Println("CronStatusDetection dateTo parse err:", err1.Error()) - continue - } - if t.After(dateFrom) && t.Before(dateTo) { - //写redis - err = PushRedisWorkOrder(v1.PointTime, v.PushObj, v.OrderName, v.OrderLevel) - if err != nil { - fmt.Println("CronStatusDetection redis set err:", err.Error()) - continue - } - break + + expr := fmt.Sprintf("%d %d %d * * %s", t.Second(), t.Minute(), t.Hour(), strings.Join(util.IntsToStrings(timingWeekly.Week), ",")) + //创建定时任务 + c.AddFunc(expr, func() { + err = svc.PushWorkOrderManage(request.PushWorkOrderReq{Id: v.Id, PushObj: pushObj}) + //err = PushObjMsg(v.PushObj, v.OrderName, v.OrderLevel) + if err != nil { + conf.Logger.Error("发送定时消息失败", zap.Error(err)) } + }) + } else { + var timingCustom request.TimingCustom + err = json.Unmarshal([]byte(v.TimingRule), &timingCustom) + if err != nil { + conf.Logger.Error("反序列化定时规则", zap.Error(err)) + continue } - } - } - fmt.Println("CronPersonalCardDate success!") -} - -type CronRedisWorkOrder struct { - PointTime int64 `json:"point_Time"` // 时间点 - PushObj string `json:"push_obj"` //推送对象 - OrderName string `json:"order_name"` // 工单名称 - OrderLevel int `json:"order_level"` // 工单等级(1紧急任务 2重要任务 3一般任务) -} - -func PushRedisWorkOrder(pointTime, pushObj, orderName string, orderLevel int) (err error) { - redis, err := client.GetRedisClient() - if err != nil { - return - } - - timeUnix, err := time.Parse(jsontime.LocalTimeFormat, pointTime) - if err != nil { - return - } - cronRedisWorkOrder := CronRedisWorkOrder{ - PointTime: timeUnix.Unix(), - PushObj: pushObj, - OrderName: orderName, - OrderLevel: orderLevel, - } - workOrderObj, err := json.Marshal(cronRedisWorkOrder) - if err != nil { - return - } - //写redis - err = redis.LPush(conf.WorkOrderPush, fmt.Sprintf("%s", workOrderObj)) - if err != nil { - return - } - return -} -// PushWorkOrderMessage 工单定时下发消息 -func PushWorkOrderMessage() { - go func() { - for { - redis, err := client.GetRedisClient() + dateFrom, err := time.Parse(jsontime.LocalDateFormat, timingCustom.DateFrom) if err != nil { - zap.L().Error(err.Error()) + conf.Logger.Error("时间类型转换错误", zap.Error(err)) continue } - workOrderList, err := redis.LRange(conf.WorkOrderPush) + dateTo, err := time.Parse(jsontime.LocalDateFormat, timingCustom.DateTo) if err != nil { - zap.L().Error(err.Error()) + conf.Logger.Error("时间类型转换错误", zap.Error(err)) + continue + } + t, err := time.Parse(jsontime.LocalDateFormat, timingCustom.PointTime) + if err != nil { + conf.Logger.Error("时间点类型转换错误", zap.Error(err)) continue } - for _, v := range workOrderList { - var cronRedisWorkOrder CronRedisWorkOrder - err = json.Unmarshal([]byte(v), &cronRedisWorkOrder) - if err != nil { - zap.L().Error(err.Error()) - continue - } - times, err1 := time.Parse(jsontime.LocalTimeFormat, time.Now().Format(jsontime.LocalTimeFormat)) - if err1 != nil { - zap.L().Error(err1.Error()) - return - } - if cronRedisWorkOrder.PointTime == times.Unix() { - var pushObj request.PushObj - err = json.Unmarshal([]byte(cronRedisWorkOrder.PushObj), &pushObj) - if err != nil { - zap.L().Error(err.Error()) - continue - } - var phones []string - for _, v1 := range pushObj.UserObj { - phones = append(phones, v1.Phone) - } - switch pushObj.PushMethod { - case 1: - //发送钉钉消息 - err = WorkOrderPushDingTalkMsg(cronRedisWorkOrder.OrderName, cronRedisWorkOrder.OrderLevel, phones) - if err != nil { - zap.L().Error(err.Error()) - } - case 2: - //发送短信 - err = WorkOrderPushNoteMsg(cronRedisWorkOrder.OrderName, phones, cronRedisWorkOrder.OrderLevel) - if err != nil { - zap.L().Error(err.Error()) - } - case 3: - //发送钉钉消息 - err = WorkOrderPushDingTalkMsg(cronRedisWorkOrder.OrderName, cronRedisWorkOrder.OrderLevel, phones) - if err != nil { - zap.L().Error(err.Error()) - } - //发送短信 - err = WorkOrderPushNoteMsg(cronRedisWorkOrder.OrderName, phones, cronRedisWorkOrder.OrderLevel) - if err != nil { - zap.L().Error(err.Error()) - } - } - //删除redis - err = redis.LRem(conf.WorkOrderPush, v) + for d := dateFrom; d.Before(dateTo); d = d.AddDate(0, 0, 1) { + expr := fmt.Sprintf("%d %d %d %d %d %d", t.Second(), t.Minute(), t.Hour(), d.Day(), d.Month(), d.Year()) + //创建定时任务 + c.AddFunc(expr, func() { + err = svc.PushWorkOrderManage(request.PushWorkOrderReq{Id: v.Id, PushObj: pushObj}) + //err = PushObjMsg(v.PushObj, v.OrderName, v.OrderLevel) if err != nil { - zap.L().Error(err.Error()) + conf.Logger.Error("发送定时消息失败", zap.Error(err)) } - } + }) } } - }() + } } diff --git a/src/util/serialize.go b/src/util/serialize.go index 2e576ee665b8130fc6134ddfaf0b88982fd3acaf..271b8bbaa7f21bfa614dbe4253bbd0ae1a68b841 100644 --- a/src/util/serialize.go +++ b/src/util/serialize.go @@ -16,3 +16,14 @@ func ConvertToString(v interface{}) string { } return string(jsonData) } + +// IntsToStrings 将int切片转换为字符串切片 +func IntsToStrings(ints []int) []string { + strs := make([]string, len(ints)) + + for i, v := range ints { + strs[i] = fmt.Sprint(v) + } + + return strs +}