Jianghan 11 ヶ月 前
コミット
18f75ef250

+ 17 - 0
telemarketingEtl/config.yaml

@@ -6,6 +6,13 @@ tidb:
     password: '=PDT49#80Z!RVv52_z'
     maxOpenConns: 80
     maxIdleConns: 5
+  callAccount:
+    dbName: Call_Accounting
+    address: 192.168.3.217:4000
+    userName: root
+    password: '=PDT49#80Z!RVv52_z'
+    maxOpenConns: 80
+    maxIdleConns: 5
 mysql:
   main:
     dbName: jianyu
@@ -94,6 +101,16 @@ openSeaTask: '0 0 0 * * *'
 deleteOpenSeaTask: '0 0 0 * * *'
 #自动退回公海
 returnOpenSeaTask: '0 0 0 * * *'
+#定时任务 近30天最多访问
+countMaxVisitTask: '0 0 * * * *'
+#定时任务 最近7天外呼次数
+countCallsTask: '0 0 * * * *'
+#定时任务 最近连续未接听次数
+missedCallsTask: '0 0 * * * *'
+#定时任务 近3天招标采购搜索次数/近3天点击标讯三级页次数
+jyListAndDetailTask: '0 0 * * * *'
+#定时任务 会员是否到期
+vipExpireTask: '0 0 0 * * *'
 #查看
 eventInfoTime: 5
 #搜索

+ 13 - 0
telemarketingEtl/config/config.go

@@ -13,6 +13,7 @@ import (
 
 var (
 	JianyuSubjectdb *mysql.Mysql
+	VoicedRecordDb  *mysql.Mysql // 通话
 	JianyuMaindb    *mysql.Mysql
 	Mgo             mg.MongodbSim
 	MgoLog          mg.MongodbSim
@@ -49,6 +50,18 @@ func init() {
 		}
 		JianyuMaindb.Init()
 	}
+	if g.Cfg().MustGet(ctx, "tidb.callAccount.dbName").String() != "" {
+		log.Println("初始化tidb")
+		VoicedRecordDb = &mysql.Mysql{
+			Address:      g.Cfg().MustGet(ctx, "tidb.callAccount.address").String(),
+			UserName:     g.Cfg().MustGet(ctx, "tidb.callAccount.userName").String(),
+			PassWord:     g.Cfg().MustGet(ctx, "tidb.callAccount.password").String(),
+			DBName:       g.Cfg().MustGet(ctx, "tidb.callAccount.dbName").String(),
+			MaxOpenConns: g.Cfg().MustGet(ctx, "tidb.callAccount.maxOpenConns").Int(),
+			MaxIdleConns: g.Cfg().MustGet(ctx, "tidb.callAccount.maxIdleConns").Int(),
+		}
+		VoicedRecordDb.Init()
+	}
 	//
 	if g.Cfg().MustGet(ctx, "mongo.main.dbName").String() != "" {
 		log.Println("初始化 mongodb main")

+ 257 - 0
telemarketingEtl/entity/Voiced.go

@@ -0,0 +1,257 @@
+package entity
+
+import (
+	"app.yhyue.com/moapp/jybase/common"
+	"app.yhyue.com/moapp/jybase/date"
+	"go.mongodb.org/mongo-driver/bson"
+	"log"
+	"sync"
+	"telemarketingEtl/config"
+	"time"
+)
+
+type Called struct {
+	phone     []string
+	frequency int
+}
+
+type Voiced struct {
+	vDate  string
+	missed int // 未接通次数
+}
+
+var (
+	CurrentDate           string
+	currentDateMx         sync.Mutex
+	firstLoad, firstLoad1 = true, true
+	mUser                 = make(map[string]*Called) // 用户
+	userPhone             = make(map[string]string)  // 手机号-用户uid
+	userPhoneMx           sync.Mutex
+	callPhone             []string                   // 所有被叫手机号
+	missedPhone           = make(map[string]*Voiced) // 所有被叫未接通手机号
+)
+
+// 最近7天外呼次数
+func CountCalled() {
+	// 判断当日第一次执行
+	currentDateMx.Lock()
+	if CurrentDate != date.NowFormat(date.Date_Short_Layout) {
+		firstLoad = true
+		CurrentDate = date.NowFormat(date.Date_Short_Layout)
+	} else {
+		firstLoad = false
+	}
+	currentDateMx.Unlock()
+
+	getUser()
+	log.Println("CountCalled 所有用户及手机号加载结束...")
+	getRecord()
+	log.Println("CountCalled 通话记录加载结束...")
+
+	for _, s := range callPhone {
+		uid := userPhone[s]
+		mUser[uid].frequency += 1
+	}
+	log.Println("通话次数匹配结束...")
+	for k, v := range mUser {
+		if b := config.JianyuSubjectdb.Update("dwd_f_crm_attribute_label", bson.M{"uid": k}, bson.M{"outbound_count": v.frequency}); !b {
+			config.JianyuSubjectdb.Insert("dwd_f_crm_attribute_label", map[string]interface{}{
+				"uid":            k,
+				"members_info":   "昨日未浏览",
+				"updatetime":     time.Now(),
+				"outbound_count": v.frequency,
+			})
+		}
+	}
+
+}
+
+func getUser() {
+	var (
+		count = 0
+	)
+	userPhoneMx.Lock()
+	defer userPhoneMx.Unlock()
+	//sql := "SELECT userId, uid, phone FROM dwd_f_userbase_baseinfo"
+	sql := "SELECT baseinfo_id, phone FROM dwd_f_userbase_contacts"
+	rows, err := config.JianyuSubjectdb.DB.Query(sql)
+	if err != nil {
+		log.Println("CountCalled---", err)
+	}
+	columns, err := rows.Columns()
+	for rows.Next() {
+		scanArgs := make([]interface{}, len(columns))
+		values := make([]interface{}, len(columns))
+		ret := make(map[string]interface{})
+		for k := range values {
+			scanArgs[k] = &values[k]
+		}
+		err = rows.Scan(scanArgs...)
+		if err != nil {
+			log.Println("CountCalled---", err)
+			break
+		}
+		for i, col := range values {
+			if v, ok := col.([]uint8); ok {
+				ret[columns[i]] = string(v)
+			} else {
+				ret[columns[i]] = col
+			}
+		}
+		count++
+		if count%2000 == 0 {
+			log.Println("CountCalled current-------", count)
+		}
+		uid := common.ObjToString(ret["baseinfo_id"])
+		phone := common.ObjToString(ret["phone"])
+		userPhone[phone] = uid
+		if mUser[uid] != nil {
+			mUser[uid].phone = append(mUser[uid].phone, phone)
+		} else {
+			mUser[uid] = &Called{
+				phone:     []string{phone},
+				frequency: 0,
+			}
+		}
+	}
+	_ = rows.Close()
+}
+
+func getRecord() {
+	var (
+		sql   string
+		count int
+		total int64
+	)
+	if firstLoad {
+		// 当日首次执行	1、全部归0 outbound_count
+		config.JianyuSubjectdb.ExecBySql("UPDATE dwd_f_crm_attribute_label SET outbound_count = 0")
+		sql = "SELECT createTime, CallNo, CalledNo FROM voice_record WHERE DATE(createTime) BETWEEN DATE(NOW() - INTERVAL 7 DAY) AND DATE(NOW()) ORDER BY createTime ASC"
+	} else {
+		aTime := time.Now().Add(-1 * time.Hour)
+		sql = "SELECT createTime, CallNo, CalledNo FROM voice_record WHERE creatime >= " + aTime.Format(time.DateTime) + " ORDER BY createTime ASC"
+	}
+	total = config.VoicedRecordDb.CountBySql(sql)
+	log.Println("CountCalled getRecord---", total)
+	if total <= 0 {
+		return
+	}
+
+	rows, err := config.VoicedRecordDb.DB.Query(sql)
+	if err != nil {
+		log.Println("CountCalled getRecord---", err)
+	}
+	columns, err := rows.Columns()
+	for rows.Next() {
+		scanArgs := make([]interface{}, len(columns))
+		values := make([]interface{}, len(columns))
+		ret := make(map[string]interface{})
+		for k := range values {
+			scanArgs[k] = &values[k]
+		}
+		err = rows.Scan(scanArgs...)
+		if err != nil {
+			log.Println("CountCalled getRecord---", err)
+			break
+		}
+		for i, col := range values {
+			if v, ok := col.([]uint8); ok {
+				ret[columns[i]] = string(v)
+			} else {
+				ret[columns[i]] = col
+			}
+		}
+		count++
+		if count%2000 == 0 {
+			log.Println("getRecord current-------", count)
+		}
+		phone := common.ObjToString(ret["CalledNo"])
+		callPhone = append(callPhone, phone)
+	}
+	_ = rows.Close()
+}
+
+// 因为同一个用户有多个手机号的情况,所以无法通过手机号直接修改
+func MissedCalls() {
+	getMissedCalls()
+	log.Println("MissedCalls 通话记录加载结束...")
+
+	for k, v := range missedPhone {
+		if b := config.JianyuSubjectdb.Update("dwd_f_crm_attribute_label", bson.M{"uid": k}, bson.M{"noanswer_count": v.missed}); !b {
+			config.JianyuSubjectdb.Insert("dwd_f_crm_attribute_label", map[string]interface{}{
+				"uid":            k,
+				"members_info":   "昨日未浏览",
+				"updatetime":     time.Now(),
+				"noanswer_count": v.missed,
+			})
+		}
+	}
+}
+
+func getMissedCalls() {
+	var (
+		sql   string
+		count int
+		total int64
+	)
+	if firstLoad1 {
+		sql = "SELECT createTime, CallNo, CalledNo FROM voice_record WHERE State != 'dealing' ORDER BY createTime ASC"
+		firstLoad1 = false
+	} else {
+		aTime := time.Now().Add(-1 * time.Hour)
+		sql = "SELECT createTime, CallNo, CalledNo FROM voice_record WHERE State != 'dealing' AND creatime >= " + aTime.Format(time.DateTime) + " ORDER BY createTime ASC"
+	}
+	total = config.VoicedRecordDb.CountBySql(sql)
+	log.Println("MissedCalls getMissedCalls---", total)
+	if total <= 0 {
+		return
+	}
+	rows, err := config.VoicedRecordDb.DB.Query(sql)
+	if err != nil {
+		log.Println("MissedCalls getMissedCalls---", err)
+	}
+	columns, err := rows.Columns()
+	for rows.Next() {
+		scanArgs := make([]interface{}, len(columns))
+		values := make([]interface{}, len(columns))
+		ret := make(map[string]interface{})
+		for k := range values {
+			scanArgs[k] = &values[k]
+		}
+		err = rows.Scan(scanArgs...)
+		if err != nil {
+			log.Println("MissedCalls getMissedCalls---", err)
+			break
+		}
+		for i, col := range values {
+			if v, ok := col.([]uint8); ok {
+				ret[columns[i]] = string(v)
+			} else {
+				ret[columns[i]] = col
+			}
+		}
+		count++
+		if count%2000 == 0 {
+			log.Println("MissedCalls getMissedCalls current-------", count)
+		}
+		phone := common.ObjToString(ret["CalledNo"])
+		vdate := common.ObjToString(ret["createTime"])
+		uid := userPhone[phone]
+		if missedPhone[uid] != nil {
+			v := missedPhone[uid]
+			if VerifyDate(v.vDate, vdate) <= 1 {
+				v.vDate = vdate
+				v.missed += 1
+			} else {
+				v.missed = 1
+				v.vDate = vdate
+			}
+		} else {
+			missedPhone[uid] = &Voiced{
+				vDate:  vdate,
+				missed: 0,
+			}
+		}
+	}
+	_ = rows.Close()
+}

+ 264 - 0
telemarketingEtl/entity/dwd_f_userbase_visit_info.go

@@ -1,8 +1,12 @@
 package entity
 
 import (
+	"app.yhyue.com/moapp/jybase/common"
+	"fmt"
+	"go.mongodb.org/mongo-driver/bson"
 	"log"
 	"regexp"
+	"strings"
 	"sync"
 	"telemarketingEtl/config"
 	"telemarketingEtl/util"
@@ -137,3 +141,263 @@ func getToday(createtime int64) (start, end string) {
 	endOfDay := time.Date(now.Year(), now.Month(), now.Day(), 23, 59, 59, 0, now.Location())
 	return startOfDay.Format(date.Date_Full_Layout), endOfDay.Format(date.Date_Full_Layout)
 }
+
+type UserVisit struct {
+	userId string
+	uId    string
+	vDate  string
+	days   int
+}
+
+// 近30天最大访问次数
+func CountMaxVisit() {
+
+	var (
+		count = 0
+
+		mArr  []*UserVisit
+		mData = make(map[string]*UserVisit)
+	)
+
+	sql := "SELECT x.*, y.uid FROM dwd_f_userbase_visit_info x LEFT JOIN dwd_f_userbase_baseinfo y ON x.userid = y.userid WHERE DATE(`date`) BETWEEN DATE(NOW() - INTERVAL 30 DAY) AND DATE(NOW()) ORDER BY `date` ASC"
+	rows, err := config.JianyuSubjectdb.DB.Query(sql)
+	if err != nil {
+		log.Println("CountMaxVisit---", err)
+	}
+	columns, err := rows.Columns()
+	for rows.Next() {
+		scanArgs := make([]interface{}, len(columns))
+		values := make([]interface{}, len(columns))
+		ret := make(map[string]interface{})
+		for k := range values {
+			scanArgs[k] = &values[k]
+		}
+		err = rows.Scan(scanArgs...)
+		if err != nil {
+			log.Println("CountMaxVisit---", err)
+			break
+		}
+		for i, col := range values {
+			if v, ok := col.([]uint8); ok {
+				ret[columns[i]] = string(v)
+			} else {
+				ret[columns[i]] = col
+			}
+		}
+		count++
+		if count%2000 == 0 {
+			log.Println("current-------", count)
+		}
+		userid := common.ObjToString(ret["userid"])
+		mDate := common.ObjToString(ret["date"])
+		mArr = append(mArr, &UserVisit{
+			userId: userid,
+			uId:    common.ObjToString(ret["uid"]),
+			vDate:  strings.Split(mDate, " ")[0],
+		})
+	}
+	_ = rows.Close()
+
+	for _, v := range mArr {
+		if mData[v.userId] != nil {
+			v1 := mData[v.userId]
+			if d := VerifyDate(v1.vDate, v.vDate); d == 1 {
+				v1.days++
+				mData[v.userId] = &UserVisit{
+					userId: v.userId,
+					uId:    v.uId,
+					vDate:  v.vDate,
+					days:   v1.days,
+				}
+			} else if d > 1 {
+				mData[v.userId] = &UserVisit{
+					userId: v.userId,
+					uId:    v.uId,
+					vDate:  v.vDate,
+					days:   1,
+				}
+			}
+		} else {
+			mData[v.userId] = &UserVisit{
+				userId: v.userId,
+				uId:    v.uId,
+				vDate:  v.vDate,
+				days:   1,
+			}
+		}
+	}
+
+	for _, v := range mData {
+		if b := config.JianyuSubjectdb.Update("dwd_f_crm_attribute_label", bson.M{"uid": v.uId}, bson.M{"continuous_visit_day": v.days}); !b {
+			config.JianyuSubjectdb.Insert("dwd_f_crm_attribute_label", map[string]interface{}{
+				"uid":                  v.days,
+				"members_info":         "昨日未浏览",
+				"updatetime":           time.Now(),
+				"continuous_visit_day": v.days,
+			})
+		}
+	}
+}
+
+// @Author jianghan
+// @Description 日期相差天数
+// @Date 2024/8/22
+func VerifyDate(d1, d2 string) int {
+	if d1 == d2 {
+		return 0
+	}
+	d11, err := time.Parse(date.Date_Short_Layout, d1)
+	if err != nil {
+		fmt.Println("Error parsing d1:", err)
+		return -1
+	}
+	d21, err := time.Parse(date.Date_Short_Layout, d2)
+	if err != nil {
+		fmt.Println("Error parsing d2:", err)
+		return -1
+	}
+	days := int(d21.Sub(d11).Hours() / 24)
+	return days
+}
+
+var (
+	firstLoad2, firstLoad3 = true, true
+
+	mSearchMap = make(map[string]int)
+)
+
+func Count3DaysSearch() {
+	var (
+		sql   string
+		count int
+		total int64
+	)
+
+	// 判断当日第一次执行
+	currentDateMx.Lock()
+	if CurrentDate != date.NowFormat(date.Date_Short_Layout) {
+		firstLoad2 = true
+		CurrentDate = date.NowFormat(date.Date_Short_Layout)
+	} else {
+		firstLoad2 = false
+	}
+	currentDateMx.Unlock()
+
+	if firstLoad2 {
+		// 当日首次执行	1、全部归0 search_count
+		config.JianyuSubjectdb.ExecBySql("UPDATE dwd_f_crm_attribute_label SET search_count = 0")
+		sql = "SELECT v.userid, b.uid, v.date, v.searchnum FROM dwd_f_userbase_visit_info v LEFT JOIN dwd_f_userbase_baseinfo b ON v.userid = b.base_user_id WHERE DATE(date) BETWEEN DATE(NOW() - INTERVAL 3 DAY) AND DATE(NOW()) ORDER BY date ASC"
+	} else {
+		aTime := time.Now().Add(-1 * time.Hour)
+		sql = "SELECT v.userid, b.uid, v.date, v.searchnum FROM dwd_f_userbase_visit_info v LEFT JOIN dwd_f_userbase_baseinfo b ON v.userid = b.base_user_id WHERE date >= " + aTime.Format(time.DateTime) + " ORDER BY date ASC"
+	}
+	total = config.JianyuSubjectdb.CountBySql(sql)
+	log.Println("Count3DaysSearch getRecord---", total)
+	if total <= 0 {
+		return
+	}
+	rows, err := config.JianyuSubjectdb.DB.Query(sql)
+	if err != nil {
+		log.Println("Count3DaysSearch---", err)
+	}
+	for rows.Next() {
+		count++
+		if count%2000 == 0 {
+			log.Println("Count3DaysSearch current-------", count)
+		}
+		var (
+			userId    string
+			uid       string
+			mDate     time.Time
+			searchNum int
+		)
+		if err = rows.Scan(&userId, &uid, &mDate, &searchNum); err != nil {
+			log.Fatal(err)
+		}
+		mSearchMap[uid] += searchNum
+	}
+	_ = rows.Close()
+
+	for k, v := range mSearchMap {
+		if b := config.JianyuSubjectdb.Update("dwd_f_crm_attribute_label", bson.M{"uid": k}, bson.M{"search_count": v}); !b {
+			config.JianyuSubjectdb.Insert("dwd_f_crm_attribute_label", map[string]interface{}{
+				"uid":          k,
+				"members_info": "昨日未浏览",
+				"updatetime":   time.Now(),
+				"search_count": v,
+			})
+		}
+	}
+}
+
+func Count3DaysDetail() {
+	var (
+		sql   string
+		count int
+		total int64
+	)
+
+	// 判断当日第一次执行
+	currentDateMx.Lock()
+	if CurrentDate != date.NowFormat(date.Date_Short_Layout) {
+		firstLoad3 = true
+		CurrentDate = date.NowFormat(date.Date_Short_Layout)
+	} else {
+		firstLoad3 = false
+	}
+	currentDateMx.Unlock()
+
+	if firstLoad3 {
+		// 当日首次执行	1、全部归0 click_detail_count
+		config.JianyuSubjectdb.ExecBySql("UPDATE dwd_f_crm_attribute_label SET click_detail_count = 0")
+		sql = "SELECT v.userid, b.uid, v.date, v.contentnum FROM dwd_f_userbase_visit_info v LEFT JOIN dwd_f_userbase_baseinfo b ON v.userid = b.base_user_id WHERE DATE(date) BETWEEN DATE(NOW() - INTERVAL 3 DAY) AND DATE(NOW()) ORDER BY date ASC"
+	} else {
+		aTime := time.Now().Add(-1 * time.Hour)
+		sql = "SELECT v.userid, b.uid, v.date, v.contentnum FROM dwd_f_userbase_visit_info v LEFT JOIN dwd_f_userbase_baseinfo b ON v.userid = b.base_user_id WHERE date >= " + aTime.Format(time.DateTime) + " ORDER BY date ASC"
+	}
+	total = config.JianyuSubjectdb.CountBySql(sql)
+	log.Println("Count3DaysDetail getRecord---", total)
+	if total <= 0 {
+		return
+	}
+	rows, err := config.JianyuSubjectdb.DB.Query(sql)
+	if err != nil {
+		log.Println("Count3DaysDetail---", err)
+	}
+	for rows.Next() {
+		count++
+		if count%2000 == 0 {
+			log.Println("Count3DaysDetail current-------", count)
+		}
+		var (
+			userId     string
+			uid        string
+			mDate      time.Time
+			contentNum int
+		)
+		if err = rows.Scan(&userId, &uid, &mDate, &contentNum); err != nil {
+			log.Fatal(err)
+		}
+		mSearchMap[uid] += contentNum
+	}
+	_ = rows.Close()
+
+	for k, v := range mSearchMap {
+		if b := config.JianyuSubjectdb.Update("dwd_f_crm_attribute_label", bson.M{"uid": k}, bson.M{"click_detail_count": v}); !b {
+			config.JianyuSubjectdb.Insert("dwd_f_crm_attribute_label", map[string]interface{}{
+				"uid":                k,
+				"members_info":       "昨日未浏览",
+				"updatetime":         time.Now(),
+				"click_detail_count": v,
+			})
+		}
+	}
+}
+
+func VipExpire() {
+	now := time.Now()
+	config.JianyuSubjectdb.ExecBySql("update dwd_f_crm_attribute_label set supersub = 0 where supersub = 1")
+	config.JianyuSubjectdb.ExecBySql("UPDATE dwd_f_data_equity_info SET supersub = 1 WHERE product_type = '超级订阅' AND endtime > ?", now.Format(date.Date_Short_Layout))
+	config.JianyuSubjectdb.ExecBySql("update dwd_f_crm_attribute_label set areasubpkg = 0 where areasubpkg = 1")
+	config.JianyuSubjectdb.ExecBySql("UPDATE dwd_f_data_equity_info SET areasubpkg = 1 WHERE product_type = '省份订阅包' AND endtime > ?", now.Format(date.Date_Short_Layout))
+}

+ 2 - 0
telemarketingEtl/go.mod

@@ -8,6 +8,7 @@ require (
 	github.com/gogf/gf/contrib/drivers/mysql/v2 v2.3.3
 	github.com/gogf/gf/v2 v2.3.3
 	github.com/robfig/cron v1.2.0
+	github.com/robfig/cron/v3 v3.0.1
 	go.mongodb.org/mongo-driver v1.9.1
 	gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22
 )
@@ -32,6 +33,7 @@ require (
 	github.com/jinzhu/inflection v1.0.0 // indirect
 	github.com/jinzhu/now v1.1.1 // indirect
 	github.com/klauspost/compress v1.13.6 // indirect
+	github.com/lunny/csession v0.0.0-20130910075847-fe53c5de3dfd // indirect
 	github.com/magiconair/properties v1.8.6 // indirect
 	github.com/mattn/go-colorable v0.1.9 // indirect
 	github.com/mattn/go-isatty v0.0.14 // indirect

+ 5 - 0
telemarketingEtl/go.sum

@@ -312,6 +312,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
 github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
 github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
 github.com/lib/pq v1.10.6/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
+github.com/lunny/csession v0.0.0-20130910075847-fe53c5de3dfd h1:DXxmBCahjva4Ox4AWOv6pR1Csv33zSj97SaLOElfIsw=
+github.com/lunny/csession v0.0.0-20130910075847-fe53c5de3dfd/go.mod h1:3w9PScemEkJoLw3OYvLWMoD8XRCmXgGwsSpT6pFpJ0g=
 github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo=
 github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
 github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
@@ -326,6 +328,7 @@ github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27k
 github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
 github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
 github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
+github.com/mattn/go-sqlite3 v1.9.0 h1:pDRiWfl+++eC2FEFRy6jXmQlvp4Yh3z1MJKg4UeYM/4=
 github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
 github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
 github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
@@ -404,6 +407,8 @@ github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
 github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
 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 v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
 github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
 github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=

+ 89 - 57
telemarketingEtl/timetask/task.go

@@ -1,14 +1,14 @@
 package timetask
 
 import (
-	"context"
+	"app.yhyue.com/moapp/jybase/date"
+	"github.com/robfig/cron/v3"
 	"log"
 	"telemarketingEtl/entity"
 	"time"
 
 	_ "github.com/gogf/gf/contrib/drivers/mysql/v2"
 	"github.com/gogf/gf/v2/os/gcfg"
-	"github.com/gogf/gf/v2/os/gcron"
 	"github.com/gogf/gf/v2/os/gctx"
 )
 
@@ -41,7 +41,9 @@ func GetStartEnd() (start, end int64) {
 	return
 }
 
-func TaskEventInfo() {
+type TaskEventInfo struct{}
+
+func (t *TaskEventInfo) Run() {
 	log.Println("开始TaskEventInfo")
 	now := time.Now()
 	end := now.Unix()
@@ -52,7 +54,9 @@ func TaskEventInfo() {
 	log.Println("结束TaskEventInfo")
 }
 
-func TaskSearchInfo() {
+type TaskSearchInfo struct{}
+
+func (t *TaskSearchInfo) Run() {
 	log.Println("开始TaskSearchInfo")
 	now := time.Now()
 	end := now.Unix()
@@ -62,7 +66,9 @@ func TaskSearchInfo() {
 	entity.SearchInfoAdd(start, end)
 }
 
-func TaskVisitInfo() {
+type TaskVisitInfo struct{}
+
+func (t *TaskVisitInfo) Run() {
 	log.Println("开始TaskVisitInfo")
 	now := time.Now()
 	end := now.Unix()
@@ -72,73 +78,99 @@ func TaskVisitInfo() {
 	log.Println("结束TaskVisitInfo")
 }
 
-func TaskOpenSea() {
+type TaskOpenSea struct{}
+
+func (t *TaskOpenSea) Run() {
 	log.Println("开始TaskOpenSea")
 	entity.GetOpenSea()
 	log.Println("结束TaskOpenSea")
 }
 
+type TaskCountMaxVisit struct{}
+
+func (t *TaskCountMaxVisit) Run() {
+	log.Println("开始TaskCountMaxVisit")
+	entity.CountMaxVisit()
+	log.Println("结束TaskCountMaxVisit")
+}
+
+type TaskCountCalled struct{}
+
+func (t *TaskCountCalled) Run() {
+	log.Println("开始TaskCountCalled")
+	entity.CountCalled()
+	log.Println("结束TaskCountCalled")
+}
+
+type TaskMissedCalls struct{}
+
+func (t *TaskMissedCalls) Run() {
+	log.Println("开始TaskMissedCalls")
+	entity.MissedCalls()
+	log.Println("结束TaskMissedCalls")
+}
+
+type TaskJyList struct{}
+
+func (t *TaskJyList) Run() {
+	log.Println("开始TaskJyList")
+	entity.Count3DaysSearch()
+	log.Println("结束TaskJyList")
+}
+
+type TaskJyDetail struct{}
+
+func (t *TaskJyDetail) Run() {
+	log.Println("开始TaskJyDetail")
+	entity.Count3DaysDetail()
+	log.Println("结束TaskJyDetail")
+}
+
+type TaskVipExpire struct{}
+
+func (t *TaskVipExpire) Run() {
+	log.Println("开始TaskVipExpire")
+	entity.VipExpire()
+	log.Println("结束TaskVipExpire")
+}
+
 // 定时任务
 func Run() {
 
 	timetaskBl := gcfg.Instance().MustGet(gctx.New(), "timetaskBl", "").Bool()
 	if timetaskBl {
 		var (
-			err error
-			ctx = gctx.New()
+			c = cron.New()
 		)
 		eventInfoTask := gcfg.Instance().MustGet(gctx.New(), "eventInfoTask", "").String()
 		searchInfoTask := gcfg.Instance().MustGet(gctx.New(), "searchInfoTask", "").String()
 		visitInfoTask := gcfg.Instance().MustGet(gctx.New(), "visitInfoTask", "").String()
 		openSeaTask := gcfg.Instance().MustGet(gctx.New(), "openSeaTask", "").String()
-		// deleteOpenSeaTask := gcfg.Instance().MustGet(gctx.New(), "deleteOpenSeaTask", "").String()
-		// returnOpenSeaTask := gcfg.Instance().MustGet(gctx.New(), "returnOpenSeaTask", "").String()
-		//
-		_, err = gcron.Add(ctx, eventInfoTask, func(ctx context.Context) {
-			TaskEventInfo()
-		}, "TaskEventInfo")
-		if err != nil {
-			panic(err)
-		}
-
-		//
-		_, err = gcron.Add(ctx, searchInfoTask, func(ctx context.Context) {
-			TaskSearchInfo()
-		}, "TaskSearchInfo")
-		if err != nil {
-			panic(err)
-		}
-		//
-		_, err = gcron.Add(ctx, visitInfoTask, func(ctx context.Context) {
-			TaskVisitInfo()
-		}, "TaskVisitInfo")
-		if err != nil {
-			panic(err)
-		}
-		//
-		_, err = gcron.Add(ctx, openSeaTask, func(ctx context.Context) {
-			TaskOpenSea()
-		}, "TaskOpenSea")
-		if err != nil {
-			panic(err)
-		}
-		//
-		// _, err = gcron.Add(ctx, deleteOpenSeaTask, func(ctx context.Context) {
-		// 	log.Println("开始DeleteOpenSea")
-		// 	entity.DeleteOpenSea()
-		// 	log.Println("结束DeleteOpenSea")
-		// }, "DeleteOpenSea")
-		// if err != nil {
-		// 	panic(err)
-		// }
-		//
-		// _, err = gcron.Add(ctx, returnOpenSeaTask, func(ctx context.Context) {
-		// 	log.Println("开始ReturnOpenSea")
-		// 	entity.ReturnOpenSea()
-		// 	log.Println("结束ReturnOpenSea")
-		// }, "ReturnOpenSea")
-		// if err != nil {
-		// 	panic(err)
-		// }
+		countMaxVisitTask := gcfg.Instance().MustGet(gctx.New(), "countMaxVisitTask", "").String()
+		countCalledVoice := gcfg.Instance().MustGet(gctx.New(), "countCallsTask", "").String()
+		missedCallsTask := gcfg.Instance().MustGet(gctx.New(), "missedCallsTask", "").String()
+		jyListAndDetailTask := gcfg.Instance().MustGet(gctx.New(), "jyListAndDetailTask", "").String()
+		vipExpireTask := gcfg.Instance().MustGet(gctx.New(), "vipExpireTask", "").String()
+
+		c.AddJob(eventInfoTask, cron.NewChain(cron.DelayIfStillRunning(cron.DefaultLogger)).Then(&TaskEventInfo{}))
+		c.AddJob(searchInfoTask, cron.NewChain(cron.DelayIfStillRunning(cron.DefaultLogger)).Then(&TaskSearchInfo{}))
+		c.AddJob(visitInfoTask, cron.NewChain(cron.DelayIfStillRunning(cron.DefaultLogger)).Then(&TaskVisitInfo{}))
+		c.AddJob(openSeaTask, cron.NewChain(cron.DelayIfStillRunning(cron.DefaultLogger)).Then(&TaskOpenSea{}))
+
+		entity.CurrentDate = date.NowFormat(date.Date_Short_Layout)
+		//近30天连续访问天数
+		c.AddJob(countMaxVisitTask, cron.NewChain(cron.DelayIfStillRunning(cron.DefaultLogger)).Then(&TaskCountMaxVisit{}))
+		//最近7天外呼次数
+		c.AddJob(countCalledVoice, cron.NewChain(cron.DelayIfStillRunning(cron.DefaultLogger)).Then(&TaskCountCalled{}))
+		//最近连续未接听次数
+		c.AddJob(missedCallsTask, cron.NewChain(cron.DelayIfStillRunning(cron.DefaultLogger)).Then(&TaskMissedCalls{}))
+		//近3天招标采购搜索次数
+		c.AddJob(jyListAndDetailTask, cron.NewChain(cron.DelayIfStillRunning(cron.DefaultLogger)).Then(&TaskJyList{}))
+		//近3天点击标讯三级页次数
+		c.AddJob(jyListAndDetailTask, cron.NewChain(cron.DelayIfStillRunning(cron.DefaultLogger)).Then(&TaskJyDetail{}))
+		//会员是否到期
+		c.AddJob(vipExpireTask, cron.NewChain(cron.DelayIfStillRunning(cron.DefaultLogger)).Then(&TaskVipExpire{}))
+
+		c.Start()
 	}
 }