wkyuer 1 сар өмнө
parent
commit
bc388e9524

+ 15 - 0
userSign/match/match.go

@@ -130,6 +130,21 @@ func (trie *TrieNode) FindWords(text string) []string {
 	return rData
 }
 
+func (trie *TrieNode) FindOneMaxStr(text string) string {
+	stringArr := trie.FindWords(text)
+	if len(stringArr) == 0 {
+		return "" // 处理空数组的情况
+	}
+
+	longest := stringArr[0]
+	for _, s := range stringArr {
+		if len(s) > len(longest) {
+			longest = s
+		}
+	}
+	return longest
+}
+
 // 在文本中查找单词
 func (trie *TrieNode) FindWordsInText(title, detail string) map[string]string {
 	words := map[string]string{}

+ 2 - 8
userSign/userAnalysis/jobLogsAnalysis.go → userSign/userAnalysis/analysisLogsAnalysis.go

@@ -8,10 +8,10 @@ import (
 	"time"
 )
 
-func (ua *UserAnalysis) GetLogRes(ctx context.Context, runTime time.Time) ([]*AnalysisRes, error) {
+func (ua *UserAnalysis) GetAnalysisLogRes(ctx context.Context, runTime time.Time) ([]*AnalysisRes, error) {
 	var (
 		sourceArr    = []string{"pc", "wx", "app"}
-		unActiveTime = []int{30, 90}
+		unActiveTime = []int{1, 30, 90}
 		returnData   = []*AnalysisRes{}
 	)
 	//活跃用户分析
@@ -37,12 +37,6 @@ func (ua *UserAnalysis) GetLogRes(ctx context.Context, runTime time.Time) ([]*An
 	if res, err := ua.Visited(ctx, runTime.AddDate(0, 0, -7)); err == nil && len(res) > 0 {
 		returnData = append(returnData, &AnalysisRes{Name: "访问过剑鱼产品", Code: "visited", Data: res, SaveOldData: true})
 	}
-	// 访问过指定页面
-	if res, err := ua.GetVisitUserAnalysis(ctx, runTime.AddDate(0, 0, -45)); err == nil && len(res) > 0 {
-		for _, t := range res {
-			returnData = append(returnData, t)
-		}
-	}
 	return returnData, nil
 }
 

+ 12 - 0
userSign/userAnalysis/analysisManager.go

@@ -12,6 +12,7 @@ import (
 type (
 	UserAnalysis struct {
 		UserMapping      map[string]BaseUserId //职位id、mongouserId对应的baseUserId
+		ClubMap          map[string]BaseUserId //电销线索
 		EntUserIdMapping map[int64]BaseUserId  //ent_id对应的baseUserId
 		FullBaseUserId   map[BaseUserId]bool   //全量BaseUserId
 
@@ -151,5 +152,16 @@ func (ua *UserAnalysis) LoadMapping() error {
 		}
 	}
 	ua.EntUserIdMapping = entIdBaseUserIdMapping
+
+	//加载线索
+	clueRes, err := g.DB("subjectdb").Query(ctx, "SELECT id,userid FROM dwd_f_crm_clue_info WHERE user!=''")
+	if err != nil {
+		return err
+	}
+	for _, m := range clueRes.List() {
+		if value, ok := newMapping[gconv.String(m["userid"])]; ok {
+			ua.ClubMap[gconv.String(m["id"])] = value
+		}
+	}
 	return nil
 }

+ 124 - 0
userSign/userAnalysis/backLogs.go

@@ -0,0 +1,124 @@
+package userAnalysis
+
+import (
+	"context"
+	"github.com/gogf/gf/v2/frame/g"
+	"github.com/gogf/gf/v2/util/gconv"
+	"strings"
+	"time"
+	"workTasks/common"
+)
+
+func (ua *UserAnalysis) GetBackLogsTagsData(ctx context.Context, t time.Time) (fData []*AnalysisRes, err error) {
+	// 留资日志
+	saleLeadsData, saleLeadsErr := ua.saleLeadsLog(ctx, t.AddDate(0, 0, -7))
+	if saleLeadsErr != nil {
+		g.Log().Errorf(ctx, "init saleLeadsLog err:%v", saleLeadsErr)
+	}
+	for _, datum := range saleLeadsData {
+		fData = append(fData, datum)
+	}
+
+	// 大会员日志
+	bigData, bigErr := ua.bigMemberLog(ctx, t.AddDate(0, 0, -1))
+	if bigErr != nil {
+		g.Log().Errorf(ctx, "init bigErr err:%v", err)
+	}
+	for _, datum := range bigData {
+		fData = append(fData, datum)
+	}
+
+	// 大会员日志
+	publicData, publicErr := ua.publicLog(ctx, t.AddDate(0, 0, -1))
+	if publicErr != nil {
+		g.Log().Errorf(ctx, "init publicErr err:%v", err)
+	}
+	for _, datum := range publicData {
+		fData = append(fData, datum)
+	}
+
+	return
+}
+
+// saleLeadsLog 查询是否留资。用于点击留资弹框
+func (ua *UserAnalysis) saleLeadsLog(ctx context.Context, t time.Time) ([]*AnalysisRes, error) {
+	clickSaleLeads7Day := map[BaseUserId]bool{}
+	sess := common.MG.DB("log").GetMgoConn()
+	defer common.MG.DB("log").DestoryMongoConn(sess)
+	it := sess.DB("qfw").C("salesLeads_logs").Find(g.Map{"date": g.Map{"$gte": t.Unix()}}).Select(g.Map{"userid": 1, "url": 1}).Iter()
+	for m := make(map[string]interface{}); it.Next(&m); {
+		var (
+			userId = gconv.String(m["userid"])
+			url    = gconv.String(m["url"])
+		)
+		if !strings.HasPrefix(url, "/salesLeads/retainedCapital") {
+			continue
+		}
+		baseUserId, ok := ua.UserMapping[userId]
+		if ok {
+			clickSaleLeads7Day[baseUserId] = true
+		}
+	}
+	return []*AnalysisRes{
+		{"近7天点击平台产品留资弹窗>=1次", "click_saleLeads_gte_1_7day", clickSaleLeads7Day, false},
+	}, nil
+}
+
+// bigMemberLog 大会员日志库
+func (ua *UserAnalysis) bigMemberLog(ctx context.Context, t time.Time) ([]*AnalysisRes, error) {
+	cacheData := map[string]map[BaseUserId]bool{
+		"/bigmember/follow/project/add":   map[BaseUserId]bool{},
+		"/bigmember/follow/ent/addFollow": map[BaseUserId]bool{},
+	}
+	sess := common.MG.DB("log").GetMgoConn()
+	defer common.MG.DB("log").DestoryMongoConn(sess)
+
+	it := sess.DB("qfw").C("bigmember_logs").Find(g.Map{"date": g.Map{"$gte": t.Unix()}}).Select(g.Map{"userid": 1, "url": 1}).Iter()
+	for m := make(map[string]interface{}); it.Next(&m); {
+		var (
+			userId = gconv.String(m["userid"])
+			urlStr = gconv.String(m["url"])
+		)
+
+		if baseUserId, ok := ua.UserMapping[userId]; ok {
+			for key, _ := range cacheData {
+				if strings.HasPrefix(urlStr, key) {
+					cacheData[key][baseUserId] = true
+				}
+			}
+		}
+	}
+	return []*AnalysisRes{
+		{"近1天新增监控项目用户", "add_monitor_project_1_day", cacheData["/bigmember/follow/project/add"], false},
+		{"近1天新增监控企业用户", "add_monitor_ent_1_day", cacheData["/bigmember/follow/ent/addFollow"], false},
+	}, nil
+}
+
+func (ua *UserAnalysis) publicLog(ctx context.Context, t time.Time) ([]*AnalysisRes, error) {
+	cacheData := map[string]map[BaseUserId]bool{
+		"/publicapply/customer/attention":    map[BaseUserId]bool{},
+		"/publicapply/subscribe/setUserInfo": map[BaseUserId]bool{}, //订阅词修改
+	}
+	sess := common.MG.DB("log").GetMgoConn()
+	defer common.MG.DB("log").DestoryMongoConn(sess)
+
+	it := sess.DB("qfw").C("publicapply_logs").Find(g.Map{"date": g.Map{"$gte": t.Unix()}}).Select(g.Map{"userid": 1, "url": 1}).Iter()
+	for m := make(map[string]interface{}); it.Next(&m); {
+		var (
+			userId = gconv.String(m["userid"])
+			urlStr = gconv.String(m["url"])
+		)
+
+		if baseUserId, ok := ua.UserMapping[userId]; ok {
+			for key, _ := range cacheData {
+				if strings.HasPrefix(urlStr, key) {
+					cacheData[key][baseUserId] = true
+				}
+			}
+		}
+	}
+	return []*AnalysisRes{
+		{"近1天新增监控业主用户", "add_monitor_buyer_1_day", cacheData["/publicapply/customer/attention"], false},
+		{"近1天调整订阅词用户", "add_change_subscribe_1_day", cacheData["/publicapply/subscribe/setUserInfo"], false},
+	}, nil
+}

+ 0 - 30
userSign/userAnalysis/buryPoint.go

@@ -1,30 +0,0 @@
-package userAnalysis
-
-import (
-	"context"
-	"github.com/gogf/gf/v2/frame/g"
-	"github.com/gogf/gf/v2/util/gconv"
-	"github.com/pkg/errors"
-	"time"
-)
-
-// GetBuryPointRes 分析埋点数据
-func (ua *UserAnalysis) GetBuryPointRes(ctx context.Context, runTime time.Time) ([]*AnalysisRes, error) {
-	//分析点击分享 近7天点击标讯分享按钮>=2
-	rData := map[BaseUserId]bool{}
-	res, err := g.DB("ckLogs").Query(ctx, "SELECT position_id FROM dwd_f_personnel_behavior WHERE page_id ='article_content' AND  breaker_name in ('QQ','朋友圈','微信') AND `date` > ? ", runTime.AddDate(0, 0, -7).Format(time.DateTime))
-	if err != nil {
-		return nil, errors.Wrap(err, "查询超级订阅购买页访问数据异常")
-	}
-	for _, m := range res.List() {
-		var (
-			position_id = gconv.String(m["position_id"])
-		)
-		if baseUserId, ok := ua.UserMapping[position_id]; !ok {
-			rData[baseUserId] = true
-		}
-	}
-	return []*AnalysisRes{
-		{"近30天电销意向客户", "buryPoint_share_7_day_gte2", rData, false},
-	}, nil
-}

+ 0 - 29
userSign/userAnalysis/jobCklogs.go

@@ -1,29 +0,0 @@
-package userAnalysis
-
-import (
-	"context"
-	"github.com/gogf/gf/v2/frame/g"
-	"github.com/gogf/gf/v2/util/gconv"
-	"github.com/pkg/errors"
-	"time"
-)
-
-func (ua *UserAnalysis) GetVisitUserAnalysis(ctx context.Context, t time.Time) ([]*AnalysisRes, error) {
-	var (
-		visitedVipBuyPage = map[BaseUserId]bool{}
-	)
-	res, err := g.DB("ckLogs").Query(ctx, "SELECT user_id,count(*) as total  FROM dwd_f_personnel_behavior WHERE `date` > ? and user_id!='' AND (url like '%jy_mobile/order/create/svip%' or url like '%/swordfish/page_big_pc/free/svip/buy%') group by user_id order BY total desc", t.Format(time.DateTime))
-	if err != nil {
-		return nil, errors.Wrap(err, "查询超级订阅购买页访问数据异常")
-	}
-
-	for _, m := range res.List() {
-		userId := gconv.String(m["user_id"])
-		baseUserId, ok := ua.UserMapping[userId]
-		if !ok {
-			continue
-		}
-		visitedVipBuyPage[baseUserId] = true
-	}
-	return []*AnalysisRes{{Name: "近45天浏览超级订阅购买页", Code: "visitedVipBuyPage", Data: visitedVipBuyPage}}, nil
-}

+ 341 - 0
userSign/userAnalysis/jobFrontLogs.go

@@ -0,0 +1,341 @@
+package userAnalysis
+
+import (
+	"context"
+	"fmt"
+	"github.com/gogf/gf/v2/frame/g"
+	"github.com/gogf/gf/v2/util/gconv"
+	"github.com/pkg/errors"
+	"time"
+	"workTasks/userSign/match"
+)
+
+// GetBuryPointRes 分析埋点数据
+func (ua *UserAnalysis) GetBuryPointRes(ctx context.Context, runTime time.Time) (fData []*AnalysisRes, err error) {
+
+	// 访问过指定页面
+	if res, err := ua.GetVisitUserAnalysis(ctx, runTime.AddDate(0, 0, -45)); err == nil && len(res) > 0 {
+		for _, t := range res {
+			fData = append(fData, t)
+		}
+	}
+
+	//7天留资用户
+	rData, err := ua.clickShareRes(ctx, runTime.AddDate(0, 0, -7))
+	if err != nil {
+		g.Log().Errorf(ctx, "init clickShareRes err:%v", err)
+	}
+	for _, datum := range rData {
+		fData = append(fData, datum)
+	}
+
+	visitBuyData, visitBuyErr := ua.visitBuyPageRes(ctx, runTime)
+	if visitBuyErr != nil {
+		g.Log().Errorf(ctx, "init visitBuyErr err:%v", visitBuyErr)
+	}
+	for _, datum := range visitBuyData {
+		fData = append(fData, datum)
+	}
+	return
+}
+
+func (ua *UserAnalysis) GetVisitUserAnalysis(ctx context.Context, t time.Time) ([]*AnalysisRes, error) {
+	var (
+		visitedVipBuyPage = map[BaseUserId]bool{}
+	)
+	res, err := g.DB("ckLogs").Query(ctx, "SELECT user_id,count(*) as total  FROM dwd_f_personnel_behavior WHERE `date` > ? and user_id!='' AND (url like '%jy_mobile/order/create/svip%' or url like '%/swordfish/page_big_pc/free/svip/buy%') group by user_id order BY total desc", t.Format(time.DateTime))
+	if err != nil {
+		return nil, errors.Wrap(err, "查询超级订阅购买页访问数据异常")
+	}
+
+	for _, m := range res.List() {
+		userId := gconv.String(m["user_id"])
+		baseUserId, ok := ua.UserMapping[userId]
+		if !ok {
+			continue
+		}
+		visitedVipBuyPage[baseUserId] = true
+	}
+	return []*AnalysisRes{{Name: "近45天浏览超级订阅购买页", Code: "visitedVipBuyPage", Data: visitedVipBuyPage}}, nil
+}
+
+func (ua *UserAnalysis) clickShareRes(ctx context.Context, t time.Time) (returnData []*AnalysisRes, err error) {
+	//分析点击分享 近7天点击标讯分享按钮>=2
+	var (
+		rData = map[BaseUserId]bool{}
+		tData = map[BaseUserId]int{}
+	)
+	res, err := g.DB("ckLogs").Query(ctx, "SELECT position_id FROM dwd_f_personnel_behavior WHERE page_id ='article_content' AND  breaker_name in ('QQ','朋友圈','微信') AND `date` > ? ", t.Format(time.DateTime))
+	if err != nil {
+		return nil, errors.Wrap(err, "查询超级订阅购买页访问数据异常")
+	}
+	for _, m := range res.List() {
+		var (
+			position_id = gconv.String(m["position_id"])
+		)
+		if baseUserId, ok := ua.UserMapping[position_id]; ok {
+			tData[baseUserId]++
+		}
+	}
+	for bid, datum := range tData {
+		if datum >= 2 {
+			rData[bid] = true
+		}
+	}
+	return []*AnalysisRes{
+		{"近7天高频分享用户", "buryPoint_share_7_day_gte2", rData, false},
+	}, nil
+}
+
+type (
+	countObj struct {
+		Seven    map[BaseUserId]int
+		One      map[BaseUserId]int
+		LoadUrl  []string
+		MiniCode string //小程序code
+	}
+	cVisit struct {
+		fullData map[string]*countObj
+		matchObj *match.TrieNode
+		now      time.Time
+	}
+)
+
+func getVisitStatic(t time.Time) *cVisit {
+	rData := &cVisit{}
+	rData.matchObj = &match.TrieNode{}
+	rData.fullData = map[string]*countObj{
+		// 超级订阅购买页单未提交订单
+		"visit_buypage_vip": &countObj{
+			Seven:   map[BaseUserId]int{},
+			One:     map[BaseUserId]int{},
+			LoadUrl: []string{"/swordfish/page_big_pc/free/svip/buy", "/jy_mobile/common/order/create/svip", "/jy_mobile/order/create/svip"},
+		},
+		"visit_buypage_member": &countObj{
+			Seven:   map[BaseUserId]int{},
+			One:     map[BaseUserId]int{},
+			LoadUrl: []string{"/big/pc/page/buy_commit", "/jy_mobile/common/order/create/bigmember"},
+		},
+		"visit_buypage_areavip": &countObj{
+			Seven:   map[BaseUserId]int{},
+			One:     map[BaseUserId]int{},
+			LoadUrl: []string{"/jy_mobile/common/order/create/areapack"},
+		},
+		"visit_buypage_buyer_report_package": &countObj{
+			Seven:   map[BaseUserId]int{},
+			One:     map[BaseUserId]int{},
+			LoadUrl: []string{"/swordfish/page_big_pc/order/download-pack/prop", "/jy_mobile/order/create/owneranalysis"},
+		},
+		"visit_buypage_winner_report_package": &countObj{
+			Seven:   map[BaseUserId]int{},
+			One:     map[BaseUserId]int{},
+			LoadUrl: []string{"/swordfish/page_big_pc/order/download-pack/ent", "/jy_mobile/order/create/enterpriseanalysis"},
+		},
+		"visit_buypage_market_report_package": &countObj{
+			Seven:   map[BaseUserId]int{},
+			One:     map[BaseUserId]int{},
+			LoadUrl: []string{"/swordfish/page_big_pc/order/download-pack/market", "/jy_mobile/order/create/marketanalysis"},
+		},
+		"visit_buypage_buyer_portrait_package": &countObj{
+			Seven:   map[BaseUserId]int{},
+			One:     map[BaseUserId]int{},
+			LoadUrl: []string{"/jy_mobile/common/order/create/buyerpack", "/page_big_pc/order/buyer-pack"},
+		},
+		"visit_buypage_attach_package": &countObj{
+			Seven:   map[BaseUserId]int{},
+			One:     map[BaseUserId]int{},
+			LoadUrl: []string{"/jy_mobile/common/order/create/filepack"},
+		},
+		"visit_buypage_ent_credit_report": &countObj{
+			Seven:   map[BaseUserId]int{},
+			One:     map[BaseUserId]int{},
+			LoadUrl: []string{"/jy_mobile/order/create/creditreport", "/swordfish/page_big_pc/order/credit-report"},
+		},
+		"visit_buypage_applet_wy": &countObj{
+			Seven:    map[BaseUserId]int{},
+			One:      map[BaseUserId]int{},
+			LoadUrl:  []string{"pages/order/create/index"},
+			MiniCode: "wy",
+		},
+		"visit_buypage_applet_clzl": &countObj{
+			Seven:    map[BaseUserId]int{},
+			One:      map[BaseUserId]int{},
+			LoadUrl:  []string{"pages/order/create/index"},
+			MiniCode: "clzl",
+		},
+		"visit_buypage_applet_ywsj": &countObj{
+			Seven:    map[BaseUserId]int{},
+			One:      map[BaseUserId]int{},
+			LoadUrl:  []string{"pages/order/create/index"},
+			MiniCode: "ywsj",
+		},
+		"visit_buypage_applet_hjcg": &countObj{
+			Seven:    map[BaseUserId]int{},
+			One:      map[BaseUserId]int{},
+			LoadUrl:  []string{"pages/order/create/index"},
+			MiniCode: "hjcg",
+		},
+		"visit_buypage_applet_jjztb": &countObj{
+			Seven:    map[BaseUserId]int{},
+			One:      map[BaseUserId]int{},
+			LoadUrl:  []string{"pages/order/create/index"},
+			MiniCode: "jjztb",
+		},
+		"visit_buypage_applet_af": &countObj{
+			Seven:    map[BaseUserId]int{},
+			One:      map[BaseUserId]int{},
+			LoadUrl:  []string{"pages/order/create/index"},
+			MiniCode: "af",
+		},
+		"visit_buypage_applet_gcsjzx": &countObj{
+			Seven:    map[BaseUserId]int{},
+			One:      map[BaseUserId]int{},
+			LoadUrl:  []string{"pages/order/create/index"},
+			MiniCode: "gcsjzx",
+		},
+		"visit_buypage_applet_fw": &countObj{
+			Seven:    map[BaseUserId]int{},
+			One:      map[BaseUserId]int{},
+			LoadUrl:  []string{"pages/order/create/index"},
+			MiniCode: "fw",
+		},
+		"visit_buypage_applet_bx": &countObj{
+			Seven:    map[BaseUserId]int{},
+			One:      map[BaseUserId]int{},
+			LoadUrl:  []string{"pages/order/create/index"},
+			MiniCode: "bx",
+		},
+		"visit_buypage_applet_cwsj": &countObj{
+			Seven:    map[BaseUserId]int{},
+			One:      map[BaseUserId]int{},
+			LoadUrl:  []string{"pages/order/create/index"},
+			MiniCode: "cwsj",
+		},
+		"visit_buypage_applet_zbdl": &countObj{
+			Seven:    map[BaseUserId]int{},
+			One:      map[BaseUserId]int{},
+			LoadUrl:  []string{"pages/order/create/index"},
+			MiniCode: "zbdl",
+		},
+		"visit_buypage_applet_glzx": &countObj{
+			Seven:    map[BaseUserId]int{},
+			One:      map[BaseUserId]int{},
+			LoadUrl:  []string{"pages/order/create/index"},
+			MiniCode: "glzx",
+		},
+	}
+	rData.now = t
+	return rData
+}
+
+func (cv *cVisit) addCount(url, miniCode, dataStr string, uid BaseUserId) {
+	matchUrl := cv.matchObj.FindOneMaxStr(url)
+	if matchUrl != "" {
+		var insertOne bool
+		if createTime, tErr := time.ParseInLocation(time.DateTime, dataStr, time.Local); tErr != nil {
+			if cv.now.AddDate(0, 0, -1).Before(createTime) {
+				insertOne = true
+			}
+		}
+
+		obj, ok := cv.fullData[matchUrl]
+		if ok && obj != nil {
+			obj.Seven[uid]++
+			if insertOne {
+				obj.Seven[uid]++
+			}
+			return
+		}
+
+		//小程序
+		if matchUrl == "pages/order/create/index" {
+			if miniObj, miniOk := cv.fullData[fmt.Sprintf("visit_buypage_applet_%s", miniCode)]; miniOk && miniObj != nil {
+				miniObj.Seven[uid]++
+				if insertOne {
+					miniObj.Seven[uid]++
+				}
+			}
+		}
+	}
+}
+
+func (cv *cVisit) getAnalysisRes() []*AnalysisRes {
+	var (
+		rData      = []*AnalysisRes{}
+		sevenTotal = map[BaseUserId]int{}
+	)
+	for code, obj := range cv.fullData {
+		var (
+			dataOne   map[BaseUserId]bool
+			dataSeven map[BaseUserId]bool
+		)
+		for basUserId, _ := range obj.One {
+			dataOne[basUserId] = true
+		}
+		for basUserId, num := range obj.Seven {
+			dataSeven[basUserId] = true
+			sevenTotal[basUserId] += num
+		}
+		rData = append(rData, &AnalysisRes{fmt.Sprintf("近1天进入%s购买页单", code), fmt.Sprintf("%s_1_day", code), dataOne, false})
+		rData = append(rData, &AnalysisRes{fmt.Sprintf("近7天进入%s购买页单", code), fmt.Sprintf("%s_7_day", code), dataSeven, false})
+	}
+	//统计7天访问大于7次
+	var sevenData = map[BaseUserId]bool{}
+	for basUserId, count := range sevenTotal {
+		if count >= 7 {
+			sevenData[basUserId] = true
+		}
+	}
+	rData = append(rData, &AnalysisRes{"近7天进入进入购买页大于等于7次", "visit_buypage_7day_gte7", sevenData, false})
+	return rData
+	//[]*AnalysisRes{
+	//{"近1天进入超级订阅购买页单未提交订单", "visit_buypage_vip_1_day", rData, false},
+	//{"近1天进入大会员购买页单未提交订单", "visit_buypage_member_1_day", rData, false},
+	//{"近1天进入省份订阅包购买页单未提交订单", "visit_buypage_areavip_1_day", rData, false},
+	//{"近1天进入业主采购分析报告下载包购买页单未提交订单", "visit_buypage_buyer_report_package_1_day", rData, false},
+	//{"近1天进入企业中标分析报告下载包购买页单未提交订单", "visit_buypage_winner_report_package_1_day", rData, false},
+	//{"近1天进入市场分析定制报告下载包购买页单未提交订单", "visit_buypage_market_report_package_1_day", rData, false},
+	//{"近1天进入采购单位画像包购买页单未提交订单", "visit_buypage_buyer_portrait_package_1_day", rData, false},
+	//{"近1天进入附件下载包购买页单未提交订单", "visit_buypage_attach_package_1_day", rData, false},
+	//{"近1天进入投标企业信用报告购买页单未提交订单", "visit_buypage_ent_credit_report_1_day", rData, false},
+	//
+	//{"近1天进入物业碎片化小程序购买页单未提交订单", "visit_buypage_applet_wy_1_day", rData, false},
+	//{"近1天进入车辆租赁碎片化小程序购买页单未提交订单", "visit_buypage_applet_clzl_1_day", rData, false},
+	//{"近1天进入印务碎片化小程序购买页单未提交订单", "visit_buypage_applet_ywsj_1_day", rData, false},
+	//{"近1天进入环境碎片化小程序购买页单未提交订单", "visit_buypage_applet_hjcg_1_day", rData, false},
+	//{"近1天进入家具碎片化小程序购买页单未提交订单", "visit_buypage_applet_jjztb_1_day", rData, false},
+	//{"近1天进入安防碎片化小程序购买页单未提交订单", "visit_buypage_applet_af_1_day", rData, false},
+	//{"近1天进入投招服工程设计咨询碎片化小程序购买页单未提交订单", "visit_buypage_applet_gcsjzx_1_day", rData, false},
+	//{"近1天进入法务碎片化小程序购买页单未提交订单", "visit_buypage_applet_fw_1_day", rData, false},
+	//
+	//{"近1天进入保服碎片化小程序购买页单未提交订单", "visit_buypage_applet_bx_1_day", rData, false},
+	//{"近1天进入招服财审碎片化小程序购买页单未提交订单", "visit_buypage_applet_cwsj_1_day", rData, false},
+	//{"近1天进入招服代理服务碎片化小程序购买页单未提交订单", "visit_buypage_applet_zbdl_1_day", rData, false},
+	//{"近1天进入招服管理咨询碎片化小程序购买页单未提交订单", "visit_buypage_applet_glzx_1_day", rData, false},
+	//}
+}
+
+// 访问购买页面
+func (ua *UserAnalysis) visitBuyPageRes(ctx context.Context, t time.Time) (returnData []*AnalysisRes, err error) {
+	visitStatic := getVisitStatic(t)
+	res, err := g.DB("ckLogs").Query(ctx, "SELECT position_id,mini_program_code,url,date FROM dwd_f_personnel_behavior WHERE `date` > ? ", t.AddDate(0, 0, -7).Format(time.DateTime))
+	if err != nil {
+		return nil, errors.Wrap(err, "查询超级订阅购买页访问数据异常")
+	}
+	for _, m := range res.List() {
+		var (
+			position_id       = gconv.String(m["position_id"])
+			urlStr            = gconv.String(m["url"])
+			mini_program_code = gconv.String(m["mini_program_code"])
+			dataStr           = gconv.String(m["date"])
+		)
+		if position_id == "" {
+			continue
+		}
+
+		if baseUserId, ok := ua.UserMapping[position_id]; ok {
+			visitStatic.addCount(urlStr, mini_program_code, dataStr, baseUserId)
+		}
+	}
+	return visitStatic.getAnalysisRes(), nil
+}

+ 114 - 11
userSign/userAnalysis/jobOrderRange.go

@@ -2,17 +2,30 @@ package userAnalysis
 
 import (
 	"context"
+	"fmt"
 	"github.com/gogf/gf/v2/frame/g"
 	"github.com/gogf/gf/v2/util/gconv"
+	"strings"
 	"time"
 )
 
+type (
+	hasOrderProductClass struct {
+		Seven map[BaseUserId]bool
+		One   map[BaseUserId]bool
+	}
+	hasOrderClass struct {
+		fullData map[string]*hasOrderProductClass
+		now      time.Time
+	}
+)
+
 // TiDBOrderRange 订单分析
 func (ua *UserAnalysis) TiDBOrderRange(ctx context.Context) ([]*AnalysisRes, error) {
 	if len(ua.UserMapping) == 0 {
 		return nil, nil
 	}
-	order, err := g.DB("jianyu").Query(ctx, "SELECT user_id,order_status,product_type,create_time,pay_money,is_backstage_order FROM dataexport_order")
+	order, err := g.DB("jianyu").Query(ctx, "SELECT user_id,order_status,product_type,create_time,pay_money,is_backstage_order,filter FROM dataexport_order")
 	if err != nil {
 		g.Log().Errorf(ctx, "读取订单异常")
 		return nil, err
@@ -24,7 +37,10 @@ func (ua *UserAnalysis) TiDBOrderRange(ctx context.Context) ([]*AnalysisRes, err
 
 		vip, member = map[BaseUserId]int{}, map[BaseUserId]int{}
 		vip45d      = map[BaseUserId]int{} //45天加购未购超级订阅
+
+		hoc = &hasOrderClass{}
 	)
+	hoc.init(now)
 	for index, m := range order.List() {
 		if index%10e4 == 0 {
 			g.Log().Infof(context.TODO(), "TiDBOrderRange %d/%d", index, order.Size())
@@ -42,16 +58,18 @@ func (ua *UserAnalysis) TiDBOrderRange(ctx context.Context) ([]*AnalysisRes, err
 		if orderStatus == 1 {
 			hasPay[baseUserId] = true
 		}
+		t, err := time.ParseInLocation(time.DateTime, gconv.String(m["create_time"]), time.Local)
+		if err != nil {
+			continue
+		}
+		//统计是否有订单
+		hoc.hasOrderStatic(product, t, baseUserId, m["filter"])
 		//统计超级订阅、大会员当月加购未购
 		if product == "VIP订阅" || product == "大会员" {
 			var (
 				pay_money          = gconv.Int(m["pay_money"])
 				is_backstage_order = gconv.Int(m["is_backstage_order"])
 			)
-			t, err := time.ParseInLocation(time.DateTime, gconv.String(m["create_time"]), time.Local)
-			if err != nil {
-				continue
-			}
 			if now.Month() == t.Month() && now.Year() == t.Year() {
 				if product == "VIP订阅" {
 					if orderStatus <= 0 && pay_money == 0 && is_backstage_order == 0 {
@@ -93,11 +111,96 @@ func (ua *UserAnalysis) TiDBOrderRange(ctx context.Context) ([]*AnalysisRes, err
 			unBuyMemberMonth[id] = true
 		}
 	}
+	r := []*AnalysisRes{
+		{Name: "付费用户", Code: "hasPay", Data: hasPay},
+		{Name: "本月加购未购超级订阅", Code: "unBuyVipMonth", Data: unBuyVipMonth},
+		{Name: "45天加购未购超级订阅", Code: "unBuyVip45Day", Data: unBuyVip45Day},
+		{Name: "本月加购未购大会员", Code: "unBuyMemberMonth", Data: unBuyMemberMonth}}
+
+	r = append(r, hoc.getAnalysisRes()...)
+
+	return r, nil
+}
+
+func (hs *hasOrderClass) init(t time.Time) {
+	tmp := map[string]*hasOrderProductClass{}
+	for _, code := range []string{"has_order_vip", "has_order_member", "has_order_areavip", "has_order_winner_report", "has_order_market_report", "has_order_buyer_report", "has_order_buyer_portrait_package", "has_order_attach_package", "has_order_ent_credit_report"} {
+		tmp[code] = &hasOrderProductClass{
+			Seven: map[BaseUserId]bool{},
+			One:   map[BaseUserId]bool{},
+		}
+	}
+
+	for _, code := range []string{"wy", "clzl", "ywsj", "hjcg", "jjztb", "af", "gcsjzx", "fw", "bx", "cwsj", "zbdl", "glzx"} {
+		tmp[fmt.Sprintf("has_order_applet_%s", code)] = &hasOrderProductClass{
+			Seven: map[BaseUserId]bool{},
+			One:   map[BaseUserId]bool{},
+		}
+	}
 
-	return []*AnalysisRes{
-			{Name: "付费用户", Code: "hasPay", Data: hasPay},
-			{Name: "本月加购未购超级订阅", Code: "unBuyVipMonth", Data: unBuyVipMonth},
-			{Name: "45天加购未购超级订阅", Code: "unBuyVip45Day", Data: unBuyVip45Day},
-			{Name: "本月加购未购大会员", Code: "unBuyMemberMonth", Data: unBuyMemberMonth}},
-		nil
+	hs.now = t
+	hs.fullData = tmp
+}
+
+func (hs *hasOrderClass) hasOrderStatic(product string, createTime time.Time, baseUserId BaseUserId, filterObj interface{}) {
+	var sevenDay, oneDay bool
+	if hs.now.AddDate(0, 0, -7).Before(createTime) {
+		sevenDay = true
+		if hs.now.AddDate(0, 0, -7).Before(createTime) {
+			oneDay = true
+		}
+	}
+	if !sevenDay {
+		return
+	}
+	var key string
+	switch product {
+	case "VIP订阅":
+		key = "has_order_vip"
+	case "大会员", "大会员-补充包", "大会员-招标文件解读", "大会员-子账号", "大会员-AI中标预测包":
+		key = "has_order_member"
+	case "省份订阅包":
+		key = "has_order_areavip"
+	case "企业中标分析报告下载包":
+		key = "has_order_winner_report"
+	case "市场分析定制报告下载包":
+		key = "has_order_market_report"
+	case "业主采购分析报告下载包":
+		key = "has_order_buyer_report"
+	case "采购单位画像包":
+		key = "has_order_buyer_portrait_package"
+	case "附件下载包":
+		key = "has_order_attach_package"
+	case "投标企业信用报告":
+		key = "has_order_ent_credit_report"
+	default:
+		//碎片化小程序
+		if strings.Index(product, "|") != -1 {
+			if filterMap := gconv.Map(filterObj); filterMap != nil && len(filterMap) > 0 {
+				code := gconv.String(filterMap["industryCode"])
+				key = fmt.Sprintf("has_order_applet_%s", code)
+			}
+		}
+	}
+	if ct := hs.fullData[key]; ct != nil {
+		ct.Seven[baseUserId] = true
+		if oneDay {
+			ct.One[baseUserId] = true
+		}
+	}
+}
+
+func (hs *hasOrderClass) getAnalysisRes() []*AnalysisRes {
+	var (
+		hasOrder7day = map[BaseUserId]bool{}
+		rData        = []*AnalysisRes{}
+	)
+	for s, class := range hs.fullData {
+		for id, _ := range class.Seven {
+			hasOrder7day[id] = true
+		}
+		rData = append(rData, &AnalysisRes{fmt.Sprintf("近1天下单%s", s), fmt.Sprintf("%s_1_day", s), class.One, false})
+	}
+	rData = append(rData, &AnalysisRes{"近7天下单用户", "has_order_7_day", hasOrder7day, false})
+	return nil
 }

+ 41 - 0
userSign/userAnalysis/saleLeads.go

@@ -0,0 +1,41 @@
+package userAnalysis
+
+import (
+	"context"
+	"github.com/gogf/gf/v2/frame/g"
+	"github.com/gogf/gf/v2/util/gconv"
+	"time"
+	"workTasks/common"
+)
+
+// GetSaleLeadsData 获取留资标签数据
+func (ua *UserAnalysis) GetSaleLeadsData(ctx context.Context, t time.Time) (fData []*AnalysisRes, err error) {
+	//7天留资用户
+	rData, err := ua.saleLeads(ctx, t.AddDate(0, 0, -7))
+	if err != nil {
+		g.Log().Errorf(ctx, "init saleLeads err:%v", err)
+	}
+	for _, datum := range rData {
+		fData = append(fData, datum)
+	}
+	return
+}
+
+// saleLeads 留资
+func (ua *UserAnalysis) saleLeads(ctx context.Context, t time.Time) ([]*AnalysisRes, error) {
+	saleLeads7Day := map[BaseUserId]bool{}
+	sess := common.MG.DB().GetMgoConn()
+	defer common.MG.DB().DestoryMongoConn(sess)
+	it := sess.DB("qfw").C("saleLeads").Find(g.Map{"createtime": g.Map{"$gte": t.Unix()}}).Select(g.Map{"userid": 1}).Iter()
+	for m := make(map[string]interface{}); it.Next(&m); {
+		var (
+			userId = gconv.String(m["userid"])
+		)
+		if baseUserId, ok := ua.UserMapping[userId]; ok {
+			saleLeads7Day[baseUserId] = true
+		}
+	}
+	return []*AnalysisRes{
+		{"7天留资用户", "save_saleLeads_7day", saleLeads7Day, false},
+	}, nil
+}

+ 6 - 5
userSign/userAnalysis/telemarketing.go

@@ -47,16 +47,17 @@ func (ua *UserAnalysis) GetTelemarketingRes(ctx context.Context, t time.Time) ([
 }
 
 func (ua *UserAnalysis) initTelemarketingIntended(ctx context.Context, jyT *jyTelemarketing, t time.Time) (err error) {
-	res, err := g.DB("subjectdb").Query(ctx, "SELECT position_id,new_value FROM dwd_f_crm_clue_change_record WHERE position_id!=-1 AND change_type='基本信息变更' AND new_value in ('意向客户','高意向客户','待签署客户') AND createtime >? ", t.Format(time.DateTime))
+	res, err := g.DB("subjectdb").Query(ctx, "SELECT clue_id,new_value FROM dwd_f_crm_clue_change_record WHERE position_id!=-1 AND change_type='基本信息变更' AND new_value in ('意向客户','高意向客户','待签署客户') AND createtime >? ", t.Format(time.DateTime))
 	if err != nil {
 		return err
 	}
 	for _, m := range res.List() {
 		var (
-			position_id = gconv.String(m["position_id"])
-			new_value   = gconv.String(m["new_value"])
+			//position_id = gconv.String(m["position_id"])
+			new_value = gconv.String(m["new_value"])
+			clue_id   = gconv.String(m["clue_id"])
 		)
-		if baseUserId, ok := ua.UserMapping[position_id]; ok {
+		if baseUserId, ok := ua.ClubMap[clue_id]; ok {
 			switch new_value {
 			case "意向客户":
 				jyT.Intended30Day[baseUserId] = true
@@ -108,7 +109,7 @@ func (ua *UserAnalysis) initFollowListen(ctx context.Context, jyT *jyTelemarketi
 }
 
 func (ua *UserAnalysis) initHasEffectiveCall(ctx context.Context, jyT *jyTelemarketing, t time.Time) (err error) {
-	res, err := g.DB("subjectdb").Query(ctx, `SELECT userid FROM dwd_f_crm_clue_info WHERE phone in (
+	res, err := g.DB("subjectdb").Query(ctx, `SELECT userid FROM dwd_f_userbase_baseinfo WHERE status=1 AND phone in (
 	SELECT phone
 	FROM (
 	  SELECT DISTINCT(CallNo) AS phone FROM Call_Accounting.voice_record WHERE CallTimeLength>60 AND  createTime>?