wcj 5 سال پیش
والد
کامیت
5b61a76aa9
55فایلهای تغییر یافته به همراه1495 افزوده شده و 213 حذف شده
  1. 2 2
      README.md
  2. 2 1
      src/config.json
  3. 2 2
      src/jfw/modules/pushent/src/config.json
  4. 1 1
      src/jfw/modules/pushent/src/followpush/push.go
  5. 1 2
      src/jfw/modules/pushent/src/rpccall/weixinrpc.go
  6. BIN
      src/jfw/modules/pushent/src/src
  7. 2 2
      src/jfw/modules/pushproject/src/config.json
  8. 1 1
      src/jfw/modules/pushproject/src/followpush/push.go
  9. 1 2
      src/jfw/modules/pushproject/src/rpccall/weixinrpc.go
  10. BIN
      src/jfw/modules/pushproject/src/src
  11. 4 2
      src/jfw/modules/pushsubscribe/src/match/config.json
  12. 2 0
      src/jfw/modules/pushsubscribe/src/match/config/config.go
  13. 11 26
      src/jfw/modules/pushsubscribe/src/match/job/matchjob.go
  14. 11 1
      src/jfw/modules/pushsubscribe/src/match/job/timetask.go
  15. 1 2
      src/jfw/modules/pushsubscribe/src/match/main.go
  16. BIN
      src/jfw/modules/pushsubscribe/src/match/match
  17. 0 13
      src/jfw/modules/pushsubscribe/src/match/util/util.go
  18. 6 3
      src/jfw/modules/pushsubscribe/src/public/rpccall.go
  19. 37 17
      src/jfw/modules/pushsubscribe/src/public/util.go
  20. 0 3
      src/jfw/modules/pushsubscribe/src/push/config/config.go
  21. 9 5
      src/jfw/modules/pushsubscribe/src/push/job/movejob.go
  22. 23 21
      src/jfw/modules/pushsubscribe/src/push/job/projectjob.go
  23. 0 4
      src/jfw/modules/pushsubscribe/src/push/job/pushjob.go
  24. 1 1
      src/jfw/modules/pushsubscribe/src/push/projecttask.json
  25. BIN
      src/jfw/modules/pushsubscribe/src/push/push
  26. 3 3
      src/jfw/modules/pushsubscribe/src/push/pusher/normalpush.go
  27. 2 1
      src/jfw/modules/pushsubscribe/src/push/pusher/repairpush.go
  28. 5 4
      src/jfw/modules/pushsubscribe/src/push/pusher/specialpush.go
  29. 1 3
      src/jfw/modules/pushsubscribe/src/push/util/db.go
  30. 3 0
      src/jfw/modules/pushsubscribe/src/push/util/entity.go
  31. 2 10
      src/jfw/modules/pushsubscribe/src/push/util/util.go
  32. 43 0
      src/jfw/modules/pushsubscribe/src/report/config.json
  33. 54 0
      src/jfw/modules/pushsubscribe/src/report/config/config.go
  34. 9 0
      src/jfw/modules/pushsubscribe/src/report/job/jobs.go
  35. 147 0
      src/jfw/modules/pushsubscribe/src/report/job/pushjob.go
  36. 349 0
      src/jfw/modules/pushsubscribe/src/report/job/statisticjob.go
  37. 56 0
      src/jfw/modules/pushsubscribe/src/report/job/timetask.go
  38. 42 0
      src/jfw/modules/pushsubscribe/src/report/main.go
  39. 27 0
      src/jfw/modules/pushsubscribe/src/report/util/db.go
  40. 3 2
      src/jfw/modules/subscribepay/src/a/init.go
  41. 8 15
      src/jfw/modules/subscribepay/src/config.json
  42. 2 6
      src/jfw/modules/subscribepay/src/config/config.go
  43. 406 0
      src/jfw/modules/subscribepay/src/report/report.go
  44. 9 7
      src/jfw/modules/subscribepay/src/util/db.go
  45. 3 0
      src/web/staticres/css/pc.css
  46. BIN
      src/web/staticres/upload/2019/09/18/201909181350298943.jpg
  47. BIN
      src/web/staticres/upload/2019/10/16/201910161617098943.jpg
  48. BIN
      src/web/staticres/upload/2019/11/13/201911131709528943.jpg
  49. 21 25
      src/web/staticres/vipsubscribe/css/subscribe_list.css
  50. 76 0
      src/web/staticres/vipsubscribe/css/vipreport_dialog.css
  51. 3 0
      src/web/staticres/vipsubscribe/image/vipreport/close.svg
  52. BIN
      src/web/staticres/vipsubscribe/image/vipreport/dialog-image.png
  53. BIN
      src/web/staticres/vipsubscribe/image/vipreport/report.png
  54. 1 1
      src/web/templates/pchelper/pushView.html
  55. 103 25
      src/web/templates/weixin/historypush.html

+ 2 - 2
README.md

@@ -3,5 +3,5 @@
 weixin sdk https://github.com/wizjin/weixin
 web用xweb框架
 
-v2.8.5
-微信端vip订阅
+v2.8.7
+订阅报告

+ 2 - 1
src/config.json

@@ -65,7 +65,8 @@
         "mymenu": "/front/wxMyOrder/myMenu",
 		"historypush": "/swordfish/historypush?times=%s",
 		"msgremind": "/front/vipsubscribe/msgremind?%s",
-		"treasurebox":"/jyTreasureBox/treasureBox"
+		"treasurebox":"/jyTreasureBox/treasureBox",
+		"vipreport":"/subscribepay/report/wxtplmsg?start=%s&end=%s&pushcount=%s"
     },
     "jy_activeset": {
         "activitystartcode": "3201000000",

+ 2 - 2
src/jfw/modules/pushent/src/config.json

@@ -16,7 +16,7 @@
     "mongodbName": "qfw",
     "mongodbPoolSize": "20",
     "mongodbServers": "192.168.3.128:27080",
-    "redisServers": "sso=192.168.3.128:3379,other=192.168.3.128:3379,push=192.168.3.128:3379",
+    "redisServers": "push=192.168.3.128:5001",
     "viewDomain": "https://web-jydev-wcj.jianyu360.cn",
     "weixinRpcServer": "127.0.0.1:8083",
     "wxcolor": "#25c78c",
@@ -25,7 +25,7 @@
     "wxtitle": "您关注的企业“%s”有新的公告信息!如果不想继续收到此类信息,可进入发现-我关注的企业进行取消。",
 	"wxdetailcolor":"#686868",
 	"appPushServiceRpc":"127.0.0.1:5566",
-	"testids":[],
+	"testids":["5d81c5a525ef8723ac0036f9"],
 	"pushPool": 30,
 	"eachPool": 30
 }

+ 1 - 1
src/jfw/modules/pushent/src/followpush/push.go

@@ -403,7 +403,7 @@ func push(fid, sname, userId string, res *[]map[string]interface{}) {
 					descriptAppend = fmt.Sprintf("\n...(共%d条)", pushnum)
 					jpushtitle = fmt.Sprintf("1. %s", jpushtitle)
 				}
-				isPushOk := jy.AppPush(Sysconfig["appPushServiceRpc"].(string), map[string]interface{}{
+				isPushOk := qrpc.AppPush(Sysconfig["appPushServiceRpc"].(string), map[string]interface{}{
 					"phoneType":      phoneType,
 					"otherPushId":    opushid,
 					"jgPushId":       jpushid,

+ 1 - 2
src/jfw/modules/pushent/src/rpccall/weixinrpc.go

@@ -2,7 +2,6 @@ package rpccall
 
 import (
 	"config"
-	"qfw/util/jy"
 	qrpc "qfw/util/rpc"
 	"strings"
 	"time"
@@ -12,7 +11,7 @@ import (
 //微信远程调用,实现模板发送消息
 func SendWinXin(p *qrpc.NotifyMsg, userId string) bool {
 	time.Sleep(10 * time.Millisecond)
-	ok, res := jy.WxPush(config.Sysconfig["weixinRpcServer"].(string), "WeiXinRpc.SendPushMsg", p)
+	ok, res := qrpc.WxPush(config.Sysconfig["weixinRpcServer"].(string), "WeiXinRpc.SendPushMsg", p)
 	if !ok && (strings.Contains(res, "[46004]") || strings.Contains(res, "[65302]") || strings.Contains(res, "[43004]") || strings.Contains(res, "[40003]")) {
 		tools.MQFW.UpdateById("user", userId, map[string]interface{}{
 			"$set": map[string]interface{}{

BIN
src/jfw/modules/pushent/src/src


+ 2 - 2
src/jfw/modules/pushproject/src/config.json

@@ -14,7 +14,7 @@
 	"mongodbName": "qfw",
 	"mongodbPoolSize": "20",
 	"mongodbServers": "192.168.3.128:27080",
-	"redisServers": "sso=192.168.3.128:3379,other=192.168.3.128:3379,push=192.168.3.128:3379",
+	"redisServers": "push=192.168.3.128:5001",
 	"rpcPort": "8759",
 	"viewDomain": "http://web-jydev-wcj.jianyu360.cn",
 	"weixinRpcServer": "127.0.0.1:8083",
@@ -24,7 +24,7 @@
 	"wxtitle": "您关注的项目《%s》有新的公告信息!如果不想继续收到此类信息,可进入发现-我关注的项目进行取消。",
 	"wxdetailcolor":"#686868",
 	"appPushServiceRpc":"127.0.0.1:5566",
-	"testids":[],
+	"testids":["5d81c5a525ef8723ac0036f9"],
 	"pushPool": 30,
 	"eachPool": 30
 }

+ 1 - 1
src/jfw/modules/pushproject/src/followpush/push.go

@@ -511,7 +511,7 @@ func push(fid interface{}, sname, scode, title, userId string, res *[]map[string
 							descriptAppend = fmt.Sprintf("\n...(共%d条)", pushnum)
 							jpushtitle = fmt.Sprintf("1. %s", jpushtitle)
 						}
-						isPushOk := jy.AppPush(Sysconfig["appPushServiceRpc"].(string), map[string]interface{}{
+						isPushOk := qrpc.AppPush(Sysconfig["appPushServiceRpc"].(string), map[string]interface{}{
 							"phoneType":      phoneType,
 							"otherPushId":    opushid,
 							"jgPushId":       jpushid,

+ 1 - 2
src/jfw/modules/pushproject/src/rpccall/weixinrpc.go

@@ -2,7 +2,6 @@ package rpccall
 
 import (
 	"config"
-	"qfw/util/jy"
 	qrpc "qfw/util/rpc"
 	"strings"
 	"time"
@@ -12,7 +11,7 @@ import (
 //微信远程调用,实现模板发送消息
 func SendWinXin(p *qrpc.NotifyMsg, userId string) bool {
 	time.Sleep(10 * time.Millisecond)
-	ok, res := jy.WxPush(config.Sysconfig["weixinRpcServer"].(string), "WeiXinRpc.SendPushMsg", p)
+	ok, res := qrpc.WxPush(config.Sysconfig["weixinRpcServer"].(string), "WeiXinRpc.SendPushMsg", p)
 	if !ok && (strings.Contains(res, "[46004]") || strings.Contains(res, "[65302]") || strings.Contains(res, "[43004]") || strings.Contains(res, "[40003]")) {
 		tools.MQFW.UpdateById("user", userId, map[string]interface{}{
 			"$set": map[string]interface{}{

BIN
src/jfw/modules/pushproject/src/src


+ 4 - 2
src/jfw/modules/pushsubscribe/src/match/config.json

@@ -1,7 +1,7 @@
 {
 	"elasticPoolSize":1,
 	"elasticSearch":"http://192.168.3.128:9800",
-	"redisServers": "pushcache_1=192.168.3.128:5000,pushcache_2_a=192.168.3.128:5001",
+	"redisServers": "pushcache_1=192.168.3.128:5000",
 	"maxPushSize":50,
 	"vipMaxPushSize":2000,
 	"mgoAddr":"192.168.3.128:27080",
@@ -11,7 +11,9 @@
 	"matchPoolSize":60,
 	"savePoolSize":5,
 	"loadUserPoolSize":60,
-	"matchDuration":60, 
+	"matchDuration":60,
+	"notMatchHour":[19,20,21,23,0,1,2,4,5],
 	"userBatch":10,
+	"pcHelperSleep":-1,
 	"pcHelper":"127.0.0.1:8082"
 }

+ 2 - 0
src/jfw/modules/pushsubscribe/src/match/config/config.go

@@ -18,8 +18,10 @@ type config struct {
 	SavePoolSize     int      `json:"savePoolSize"`
 	LoadUserPoolSize int      `json:"loadUserPoolSize"`
 	MatchDuration    int64    `json:"matchDuration"`
+	NotMatchHour     []int    `json:"notMatchHour"`
 	UserBatch        int      `json:"userBatch"`
 	PcHelper         string   `json:"pcHelper"`
+	PcHelperSleep    int      `json:"pcHelperSleep"`
 }
 
 type taskConfig struct {

+ 11 - 26
src/jfw/modules/pushsubscribe/src/match/job/matchjob.go

@@ -5,8 +5,6 @@ import (
 	"fmt"
 	. "match/config"
 	. "match/matcher"
-	mutil "match/util"
-	"public"
 	. "public"
 	"qfw/util"
 	"qfw/util/elastic"
@@ -21,11 +19,8 @@ import (
 	"gopkg.in/mgo.v2/bson"
 )
 
-var (
-	SaveFields = []string{"_id", "area", "city", "buyerclass", "publishtime", "s_subscopeclass", "subtype", "title", "toptype", "type"}
-)
-
 const (
+	DbName       = "qfw"
 	DB           = "bidding"
 	MaxId        = `{"query":{"filtered":{"filter":{"bool":{"must":{"range":{"id":{"gt":"%s"}}}}}}},"_source":["_id","comeintime"],"sort":{"id":"desc"},"from":0,"size":1}`
 	ProjectQuery = `{"query":{"filtered":{"filter":{"term":{"list.infoid":"%s"}}}},"_source":["_id","list.infoid"],"sort":{"id":"desc"},"from":0,"size":1}`
@@ -144,7 +139,7 @@ func (m *MatchJob) LoadBidding(lastId, newId string, lastTime int64) *[]map[stri
 		res = append(res, temp)
 		//信息缓存3天
 		info := map[string]interface{}{}
-		for _, v := range SaveFields {
+		for _, v := range InfoSaveFields {
 			if v == "_id" || temp[v] == nil {
 				continue
 			}
@@ -170,7 +165,7 @@ func (m *MatchJob) OnceUserBatch(batchIndex int, lastUserId *string) (int, *VipU
 	}
 	_idq := map[string]interface{}{}
 	if len(Config.TestIds) > 0 {
-		_idq["$in"] = mutil.ToObjectIds(Config.TestIds)
+		_idq["$in"] = ToObjectIds(Config.TestIds)
 	}
 	if *lastUserId != "" {
 		_idq["$gt"] = bson.ObjectIdHex(*lastUserId)
@@ -181,7 +176,7 @@ func (m *MatchJob) OnceUserBatch(batchIndex int, lastUserId *string) (int, *VipU
 	logger.Info("开始加载第", batchIndex, "批用户", q)
 	session := mongodb.GetMgoConn()
 	defer mongodb.DestoryMongoConn(session)
-	query := session.DB(DbName).C(User).Find(&q).Select(public.UserCollFields).Sort("_id").Iter()
+	query := session.DB(DbName).C(User).Find(&q).Select(UserCollFields).Sort("_id").Iter()
 	n := 0
 	freeUser := NewFreeUser() //免费所有用户
 	vipUser := NewVipUser()   //vip所有用户
@@ -206,7 +201,7 @@ func (m *MatchJob) OnceUserBatch(batchIndex int, lastUserId *string) (int, *VipU
 				<-loadUserPool
 				loadUserWaitGroup.Done()
 			}()
-			user, o_msgset := public.NewUserInfoByUserColl(temp)
+			user, o_msgset := NewUserInfoByUserColl(Config.PcHelper, Config.PcHelperSleep, temp)
 			if user == nil {
 				return
 			}
@@ -214,10 +209,6 @@ func (m *MatchJob) OnceUserBatch(batchIndex int, lastUserId *string) (int, *VipU
 			var allKeySet []*KeySet
 			var err error
 			if isVipUser {
-				if dayCount := redis.GetInt("pushcache_2_a", DayCountKey(user.Id)); dayCount >= Config.VipMaxPushSize {
-					logger.Info("vip用户达到一天最大推送数量", user.Id, dayCount)
-					return
-				}
 				vip_items, _ := o_msgset["a_items"].([]interface{})
 				for _, v := range vip_items {
 					vip_item, _ := v.(map[string]interface{})
@@ -315,9 +306,13 @@ func (m *MatchJob) OnceUserBatch(batchIndex int, lastUserId *string) (int, *VipU
 				}
 				//vip付费-采购单位行业
 				vip_buyerclass, _ := o_msgset["a_buyerclass"].([]interface{})
+				//如果有关键词 有采购单位行业,行业加上“其它”
 				if len(vip_buyerclass) == 0 {
 					vipUser.Add("", user, &vipUser.BuyerclassUsers)
 				} else {
+					if len(keys) > 0 {
+						vip_buyerclass = append(vip_buyerclass, "其它")
+					}
 					for _, v := range vip_buyerclass {
 						s_v, _ := v.(string)
 						if s_v == "" {
@@ -527,23 +522,13 @@ func (m *MatchJob) ToMatch(batchIndex int, matcher Matcher, datas *[]map[string]
 			for _, v2 := range *infos {
 				title := util.ObjToString((*v2.Info)["title"])
 				_id := util.ObjToString((*v2.Info)["_id"])
-				pushInfoKey := PushInfoKey(user.Id, _id)
 				if matchTitle[title] {
 					filterId[_id] = true
 					continue
 				}
 				matchTitle[title] = true
-				isExists, err := redis.Exists(Pushcache_2_a, pushInfoKey)
-				if err != nil {
-					logger.Error(pushInfoKey, "推送信息redis判重出错", err)
-				}
-				if isExists {
-					filterId[_id] = true
-					continue
-				}
-				redis.Put(Pushcache_2_a, pushInfoKey, 1, OneDaySecond)
 				info := map[string]interface{}{}
-				for _, field := range SaveFields {
+				for _, field := range InfoSaveFields {
 					if (*v2.Info)[field] == nil {
 						continue
 					}
@@ -660,7 +645,7 @@ func (m *MatchJob) ToRelationProject(projectUser *map[*UserInfo]*[]string, myMat
 					projectId = project.Id
 					list_last_infoid = project.List_last_infoid
 				} else {
-					projects := elastic.Get("projectset", "projectset", fmt.Sprintf(ProjectQuery, _id))
+					projects := elastic.Get(Projectset, Projectset, fmt.Sprintf(ProjectQuery, _id))
 					if projects == nil || len(*projects) == 0 {
 						continue
 					}

+ 11 - 1
src/jfw/modules/pushsubscribe/src/match/job/timetask.go

@@ -23,7 +23,17 @@ func (m *MatchTimeTask) Execute() {
 	hour := time.Now().Hour()
 	//23点到1点之间,不执行定时任务
 	//订阅付费有每天0点的定时任务删除pushspace_temp表的数据,会有冲突
-	if hour < 23 && hour > 1 {
+	isRun := true
+	if hour == 0 {
+		isRun = false
+	}
+	for _, v := range Config.NotMatchHour {
+		if v == hour {
+			isRun = false
+			break
+		}
+	}
+	if isRun {
 		Jobs.Match.Execute()
 		util.WriteSysConfig("./task.json", &TaskConfig)
 	}

+ 1 - 2
src/jfw/modules/pushsubscribe/src/match/main.go

@@ -6,7 +6,6 @@ import (
 	"log"
 	. "match/config"
 	"match/job"
-	. "public"
 	"qfw/util/elastic"
 	"qfw/util/mongodb"
 	"qfw/util/redis"
@@ -19,7 +18,7 @@ func main() {
 	flag.Parse()
 	logger.SetConsole(false)
 	logger.SetRollingDaily("./logs", "match.log")
-	mongodb.InitMongodbPool(Config.MgoSize, Config.MgoAddr, DbName)
+	mongodb.InitMongodbPool(Config.MgoSize, Config.MgoAddr, job.DbName)
 	redis.InitRedis(Config.RedisServers)
 	elastic.InitElasticSize(Config.ElasticSearch, Config.ElasticPoolSize)
 	log.Println("订阅推送-匹配数据程序启动。。。")

BIN
src/jfw/modules/pushsubscribe/src/match/match


+ 0 - 13
src/jfw/modules/pushsubscribe/src/match/util/util.go

@@ -1,13 +0,0 @@
-package util
-
-import (
-	"gopkg.in/mgo.v2/bson"
-)
-
-func ToObjectIds(ids []string) []bson.ObjectId {
-	_ids := []bson.ObjectId{}
-	for _, v := range ids {
-		_ids = append(_ids, bson.ObjectIdHex(v))
-	}
-	return _ids
-}

+ 6 - 3
src/jfw/modules/pushsubscribe/src/public/rpccall.go

@@ -2,17 +2,20 @@ package public
 
 import (
 	"net/rpc"
-	. "push/config"
 	"qfw/util"
+	"time"
 
 	"github.com/donnie4w/go-logger/logger"
 )
 
 //
-func PcHelperIsOnLine(phone string) bool {
+func PcHelperIsOnLine(address, phone string, sleep int) bool {
 	defer util.Catch()
+	if sleep > 0 {
+		time.Sleep(time.Duration(sleep) * time.Millisecond)
+	}
 	var repl string
-	client, err := rpc.DialHTTP("tcp", Config.PcHelper)
+	client, err := rpc.DialHTTP("tcp", address)
 	if err != nil {
 		logger.Error(err.Error())
 		return false

+ 37 - 17
src/jfw/modules/pushsubscribe/src/public/util.go

@@ -8,27 +8,30 @@ import (
 	"time"
 
 	"github.com/donnie4w/go-logger/logger"
+	"gopkg.in/mgo.v2/bson"
 )
 
 const (
-	BulkSize           = 20
-	BigBulkSize        = 100
-	OneDaySecond       = 86400
-	SevenDay           = 604800
-	User               = "user"
-	Bidding            = "bidding"
-	Pushspace_project  = "pushspace_project"
-	Pushspace_temp     = "pushspace_temp"
-	Pushspace_vip      = "pushspace_vip"
-	Pushspace_vip_fail = "pushspace_vip_fail"
-	Pushspace_fail     = "pushspace_fail"
-	Pushspace          = "pushspace"
-	Pushcache_1        = "pushcache_1"
-	Pushcache_2_a      = "pushcache_2_a"
+	BulkSize            = 20
+	BigBulkSize         = 100
+	OneDaySecond        = 86400
+	SevenDay            = 604800
+	User                = "user"
+	Bidding             = "bidding"
+	Projectset          = "projectset"
+	Pushspace_project   = "pushspace_project"
+	Pushspace_statistic = "pushspace_statistic"
+	Pushspace_temp      = "pushspace_temp"
+	Pushspace_vip       = "pushspace_vip"
+	Pushspace_vip_fail  = "pushspace_vip_fail"
+	Pushspace_fail      = "pushspace_fail"
+	Pushspace           = "pushspace"
+	Pushcache_1         = "pushcache_1"
+	Pushcache_2_a       = "pushcache_2_a"
 )
 
 var (
-	DbName         = "qfw"
+	Se             = util.SimpleEncrypt{Key: "topnet"}
 	MailReg        = regexp.MustCompile("^.+@.+$")
 	UserCollFields = map[string]interface{}{
 		"_id":             1,
@@ -49,6 +52,16 @@ var (
 		"s_nickname":      1,
 		"l_firstpushtime": 1,
 	}
+	InfoSaveFields = []string{"_id", "area", "city", "buyerclass", "publishtime", "s_subscopeclass", "subtype", "title", "toptype", "type"}
+	WeekNum        = map[string]int{
+		"Monday":    1,
+		"Tuesday":   2,
+		"Wednesday": 3,
+		"Thursday":  4,
+		"Friday":    5,
+		"Saturday":  6,
+		"Sunday":    7,
+	}
 )
 
 func IsVipUser(vipStatus int) bool {
@@ -156,7 +169,7 @@ func ModeTransform(userType int, o_msgset map[string]interface{}) (int, int, int
 }
 
 //根据user表中的数据,生成UserInfo
-func NewUserInfoByUserColl(temp map[string]interface{}) (user *UserInfo, o_msgset map[string]interface{}) {
+func NewUserInfoByUserColl(address string, sleep int, temp map[string]interface{}) (user *UserInfo, o_msgset map[string]interface{}) {
 	userId := util.BsonIdToSId(temp["_id"])
 	s_m_openid := util.ObjToString(temp["s_m_openid"])
 	a_m_openid := util.ObjToString(temp["a_m_openid"])
@@ -185,7 +198,7 @@ func NewUserInfoByUserColl(temp map[string]interface{}) (user *UserInfo, o_msgse
 		logger.Info("过滤掉,app用户没有登录", userId)
 		return
 	} else if (userType == 1 || (userType == 5 && isPush == 0)) && jpushid == "" && (opushid == "" || appPhoneType == "") {
-		if s_phone == "" || !PcHelperIsOnLine(s_phone) {
+		if s_phone == "" || !PcHelperIsOnLine(address, s_phone, sleep) {
 			logger.Info("过滤掉,s_phone为空或者pc助手s_phone不在线", userId)
 			return
 		} else {
@@ -236,3 +249,10 @@ func NewUserInfoByUserColl(temp map[string]interface{}) (user *UserInfo, o_msgse
 func PushInfoKey(userId, infoId string) string {
 	return fmt.Sprintf("pushinfo_%s_%s", userId, infoId)
 }
+func ToObjectIds(ids []string) []bson.ObjectId {
+	_ids := []bson.ObjectId{}
+	for _, v := range ids {
+		_ids = append(_ids, bson.ObjectIdHex(v))
+	}
+	return _ids
+}

+ 0 - 3
src/jfw/modules/pushsubscribe/src/push/config/config.go

@@ -3,7 +3,6 @@ package config
 import (
 	"qfw/util"
 	"qfw/util/mail"
-	"regexp"
 	"strings"
 )
 
@@ -90,8 +89,6 @@ type projectTask struct {
 
 var (
 	Gmails         []*mail.GmailAuth
-	Se             = util.SimpleEncrypt{Key: "topnet"}
-	Re             = regexp.MustCompile("<[^>]+>([^<]+)?<[^>]+>")
 	Config         *config
 	ProjectTask    *projectTask
 	WxGroupLen     int

+ 9 - 5
src/jfw/modules/pushsubscribe/src/push/job/movejob.go

@@ -15,6 +15,10 @@ import (
 	mgo "gopkg.in/mgo.v2"
 )
 
+var (
+	MoveFields = []string{"s_m_openid", "a_m_openid", "phone", "usertype", "jpushid", "opushid", "words", "ratemode", "wxpush", "apppush", "mailpush", "pchelperpush", "timestamp", "subscribe", "applystatus", "appphonetype", "email", "size", "modifydate", "mergeorder", "nickname", "firstpushtime", "vipstatus"}
+)
+
 type MoveUser struct {
 	info      map[string]interface{}
 	ids       []interface{}
@@ -42,7 +46,7 @@ func (m *MoveJob) Execute() {
 			"$in": Config.TestIds,
 		}
 	}
-	it := sess.DB(DbName).C(Pushspace_temp).Find(query).Sort("userid").Iter()
+	it := sess.DB(Config.Mongodb.DbName).C(Pushspace_temp).Find(query).Sort("userid").Iter()
 	moveUsers := map[string]*MoveUser{}
 	index, number, length := 0, 0, 0
 	//
@@ -148,7 +152,7 @@ func (m *MoveJob) merge(number *int, nowUnix int64, moveUsers map[string]*MoveUs
 			sess := mongodb.GetMgoConn()
 			defer mongodb.DestoryMongoConn(sess)
 			var data map[string]interface{}
-			sess.DB(DbName).C(Pushspace).Find(map[string]interface{}{"userid": userId}).Select(map[string]interface{}{"list": 1}).One(&data)
+			sess.DB(Config.Mongodb.DbName).C(Pushspace).Find(map[string]interface{}{"userid": userId}).Select(map[string]interface{}{"list": 1}).One(&data)
 			if data == nil { //批量新增
 				mergeLock.Lock()
 				saveArray = append(saveArray, moveUser.info)
@@ -240,7 +244,7 @@ func (m *MoveJob) saveBulk(sess *mgo.Session, saves *[]map[string]interface{}, d
 		sess = mongodb.GetMgoConn()
 		defer mongodb.DestoryMongoConn(sess)
 	}
-	coll := sess.DB(DbName).C(Pushspace)
+	coll := sess.DB(Config.Mongodb.DbName).C(Pushspace)
 	bulk := coll.Bulk()
 	for _, v := range *saves {
 		bulk.Insert(v)
@@ -258,7 +262,7 @@ func (m *MoveJob) updateBulk(sess *mgo.Session, array_q, array_s *[]map[string]i
 		sess = mongodb.GetMgoConn()
 		defer mongodb.DestoryMongoConn(sess)
 	}
-	coll := sess.DB(DbName).C(Pushspace)
+	coll := sess.DB(Config.Mongodb.DbName).C(Pushspace)
 	bulk := coll.Bulk()
 	for k, v := range *array_q {
 		bulk.Update(v, (*array_s)[k])
@@ -277,7 +281,7 @@ func (m *MoveJob) delBulk(sess *mgo.Session, array *[]interface{}) {
 		sess = mongodb.GetMgoConn()
 		defer mongodb.DestoryMongoConn(sess)
 	}
-	coll := sess.DB(DbName).C(Pushspace_temp)
+	coll := sess.DB(Config.Mongodb.DbName).C(Pushspace_temp)
 	count := 0
 	bulk := coll.Bulk()
 	for _, v := range *array {

+ 23 - 21
src/jfw/modules/pushsubscribe/src/push/job/projectjob.go

@@ -48,7 +48,7 @@ func (p *ProjectPushJob) Execute() {
 				sess := mongodb.GetMgoConn()
 				defer mongodb.DestoryMongoConn(sess)
 				var u map[string]interface{}
-				sess.DB(DbName).C(User).FindId(bson.ObjectIdHex(userId)).Select(map[string]interface{}{
+				sess.DB(Config.Mongodb.DbName).C(User).FindId(bson.ObjectIdHex(userId)).Select(map[string]interface{}{
 					"o_vipjy.i_projectmatch": 1,
 				}).One(&u)
 				if u == nil || len(u) == 0 {
@@ -115,16 +115,15 @@ func (p *ProjectPushJob) Execute() {
 							}
 							length++
 							//满足条件,可以推送
-							*sortList = append(*sortList, &MatchInfo{
-								Info: &map[string]interface{}{
-									"area":       util.ObjToString(plm["area"]),
-									"city":       util.ObjToString(plm["city"]),
-									"_id":        infoId,
-									"toptype":    util.ObjToString(plm["toptype"]),
-									"subtype":    util.ObjToString(plm["subtype"]),
-									"buyerclass": util.ObjToString(plm["buyerclass"]),
-								},
-							})
+							info := map[string]interface{}{}
+							for _, field := range InfoSaveFields {
+								if field == "_id" || plm[field] == nil {
+									continue
+								}
+								info[field] = plm[field]
+							}
+							info["_id"] = infoId
+							*sortList = append(*sortList, &MatchInfo{Info: &info})
 						}
 						if infoId != maxId {
 							updateProject = append(updateProject, []map[string]interface{}{
@@ -192,12 +191,15 @@ func (p *ProjectPushJob) Execute() {
 
 //分批次加载pushspace_project表数据
 func (p *ProjectPushJob) loadPushspace_project(batchIndex int, startId *string) (int, *map[string][]map[string]interface{}) {
-	var query map[string]interface{}
+	query := map[string]interface{}{}
 	if *startId != "" {
-		query = map[string]interface{}{
-			"_id": map[string]interface{}{
-				"$lt": bson.ObjectIdHex(*startId),
-			},
+		query["_id"] = map[string]interface{}{
+			"$lt": bson.ObjectIdHex(*startId),
+		}
+	}
+	if len(Config.TestIds) > 0 {
+		query["userid"] = map[string]interface{}{
+			"$in": Config.TestIds,
 		}
 	}
 	//query = map[string]interface{}{
@@ -211,7 +213,7 @@ func (p *ProjectPushJob) loadPushspace_project(batchIndex int, startId *string)
 	prevUserId := ""
 	sess := mongodb.GetMgoConn()
 	defer mongodb.DestoryMongoConn(sess)
-	it := sess.DB(DbName).C(Pushspace_project).Find(query).Select(map[string]interface{}{
+	it := sess.DB(Config.Mongodb.DbName).C(Pushspace_project).Find(query).Select(map[string]interface{}{
 		"_id":       1,
 		"maxid":     1,
 		"subtypes":  1,
@@ -250,7 +252,7 @@ func (p *ProjectPushJob) loadProject() *sync.Map {
 	//query = map[string]interface{}{
 	//"_id": bson.ObjectIdHex("5da828a6e138234108b4c02e"),
 	//}
-	it := sess.DB(DbName).C(Config.ProjectMongodb.CollName).Find(query).Select(map[string]interface{}{
+	it := sess.DB(Config.ProjectMongodb.DbName).C(Config.ProjectMongodb.CollName).Find(query).Select(map[string]interface{}{
 		"_id":  1,
 		"list": 1,
 	}).Sort("_id").Iter()
@@ -283,10 +285,10 @@ func (p *ProjectPushJob) loadProject() *sync.Map {
 
 //清理三个月前的数据
 func (p *ProjectPushJob) Clear() {
-	logger.Error("开始清理过期的关联项目数据。。。")
+	logger.Info("开始清理过期的关联项目数据。。。")
 	sess := mongodb.GetMgoConn()
 	defer mongodb.DestoryMongoConn(sess)
-	_, err := sess.DB(DbName).C(Pushspace_project).RemoveAll(map[string]interface{}{
+	_, err := sess.DB(Config.Mongodb.DbName).C(Pushspace_project).RemoveAll(map[string]interface{}{
 		"createtime": map[string]interface{}{
 			"$lt": time.Now().AddDate(0, -3, 0).Unix(),
 		},
@@ -294,6 +296,6 @@ func (p *ProjectPushJob) Clear() {
 	if err != nil {
 		logger.Error("清理过期的关联项目数据错误", err)
 	} else {
-		logger.Error("清理过期的关联项目数据结束。。。")
+		logger.Info("清理过期的关联项目数据结束。。。")
 	}
 }

+ 0 - 4
src/jfw/modules/pushsubscribe/src/push/job/pushjob.go

@@ -21,10 +21,6 @@ import (
 	"gopkg.in/mgo.v2/bson"
 )
 
-var (
-	MoveFields = []string{"s_m_openid", "a_m_openid", "phone", "usertype", "jpushid", "opushid", "words", "ratemode", "wxpush", "apppush", "mailpush", "pchelperpush", "timestamp", "subscribe", "applystatus", "appphonetype", "email", "size", "modifydate", "mergeorder", "nickname", "firstpushtime"}
-)
-
 func init() {
 	if Config.MinutePushSize > 0 {
 		putil.LimitMaxOneMinutePush(&Jobs.Push.minutePushPool, Config.MinutePushSize)

+ 1 - 1
src/jfw/modules/pushsubscribe/src/push/projecttask.json

@@ -1 +1 @@
-{"pici":1573806347}
+{"pici":1576221579}

BIN
src/jfw/modules/pushsubscribe/src/push/push


+ 3 - 3
src/jfw/modules/pushsubscribe/src/push/pusher/normalpush.go

@@ -76,7 +76,7 @@ func (n *NormalPush) AfterPush(pushResult *putil.PushResult, u *UserInfo, user m
 	//判断是否要删除数据
 	sess := mongodb.GetMgoConn()
 	defer mongodb.DestoryMongoConn(sess)
-	err := sess.DB(DbName).C(Pushspace).RemoveId(user["_id"])
+	err := sess.DB(Config.Mongodb.DbName).C(Pushspace).RemoveId(user["_id"])
 	if err != nil {
 		logger.Error("推送任务", u.Id, "删除出错", err)
 	}
@@ -93,7 +93,7 @@ func (n *NormalPush) AfterPush(pushResult *putil.PushResult, u *UserInfo, user m
 		if pushResult.MailStatus == -1 {
 			user["mailfail"] = 1
 		}
-		_, err := sess.DB(DbName).C(Pushspace_fail).UpsertId(user["_id"], map[string]interface{}{"$set": user})
+		_, err := sess.DB(Config.Mongodb.DbName).C(Pushspace_fail).UpsertId(user["_id"], map[string]interface{}{"$set": user})
 		if err != nil {
 			logger.Error("推送任务", u.Id, "更新出错", err)
 		}
@@ -142,7 +142,7 @@ func (n *NormalPush) vipTempSave(u *UserInfo, pushParam *putil.PushParam) {
 	sess := mongodb.GetMgoConn()
 	defer mongodb.DestoryMongoConn(sess)
 	var data map[string]interface{}
-	coll := sess.DB(DbName).C(Pushspace_vip)
+	coll := sess.DB(Config.Mongodb.DbName).C(Pushspace_vip)
 	coll.Find(map[string]interface{}{
 		"userid":   u.Id,
 		"status":   1,

+ 2 - 1
src/jfw/modules/pushsubscribe/src/push/pusher/repairpush.go

@@ -2,6 +2,7 @@ package pusher
 
 import (
 	. "public"
+	. "push/config"
 	putil "push/util"
 	"qfw/util/mongodb"
 	"strings"
@@ -69,7 +70,7 @@ func (r *RepairPush) GetPushParam(mailPush bool, u *UserInfo, sl *SortList) *put
 func (r *RepairPush) AfterPush(pushResult *putil.PushResult, u *UserInfo, user map[string]interface{}) {
 	sess := mongodb.GetMgoConn()
 	defer mongodb.DestoryMongoConn(sess)
-	coll := sess.DB(DbName).C(Pushspace_fail)
+	coll := sess.DB(Config.Mongodb.DbName).C(Pushspace_fail)
 	if pushResult == nil || (pushResult.WxStatus != -1 && pushResult.AppStatus != -1 && pushResult.MailStatus != -1) {
 		err := coll.RemoveId(user["_id"])
 		if err != nil {

+ 5 - 4
src/jfw/modules/pushsubscribe/src/push/pusher/specialpush.go

@@ -49,14 +49,15 @@ func (s *SpecialPush) GetUserInfo(user map[string]interface{}) (*UserInfo, *puti
 	sess := mongodb.GetMgoConn()
 	defer mongodb.DestoryMongoConn(sess)
 	var u map[string]interface{}
-	sess.DB(DbName).C(User).FindId(bson.ObjectIdHex(userId)).Select(UserCollFields).One(&u)
+	sess.DB(Config.Mongodb.DbName).C(User).FindId(bson.ObjectIdHex(userId)).Select(UserCollFields).One(&u)
 	if u == nil || len(u) == 0 {
 		logger.Error(userId, "没有找到该用户信息")
 		s.deletePushspaceVip(user)
 		return nil, nil
 	}
-	userInfo, _ := NewUserInfoByUserColl(u)
+	userInfo, _ := NewUserInfoByUserColl(Config.PcHelper, Config.PcHelperSleep, u)
 	if userInfo == nil {
+		s.deletePushspaceVip(user)
 		return nil, nil
 	}
 	if !IsVipUser(userInfo.VipStatus) {
@@ -105,7 +106,7 @@ func (s *SpecialPush) AfterPush(pushResult *putil.PushResult, u *UserInfo, user
 			user["mailfail"] = 1
 		}
 		user["failtime"] = time.Now().Unix()
-		err := sess.DB(DbName).C(Pushspace_vip_fail).Insert(user)
+		err := sess.DB(Config.Mongodb.DbName).C(Pushspace_vip_fail).Insert(user)
 		if err != nil {
 			logger.Error(u.Id, "新增出错", err)
 		}
@@ -116,7 +117,7 @@ func (s *SpecialPush) AfterPush(pushResult *putil.PushResult, u *UserInfo, user
 func (s *SpecialPush) deletePushspaceVip(u map[string]interface{}) {
 	sess := mongodb.GetMgoConn()
 	defer mongodb.DestoryMongoConn(sess)
-	err := sess.DB(DbName).C(Pushspace_vip).RemoveId(u["_id"])
+	err := sess.DB(Config.Mongodb.DbName).C(Pushspace_vip).RemoveId(u["_id"])
 	if err != nil {
 		logger.Error(u["userid"], "删除出错", err)
 	}

+ 1 - 3
src/jfw/modules/pushsubscribe/src/push/util/db.go

@@ -2,7 +2,6 @@ package util
 
 import (
 	"log"
-	. "public"
 	. "push/config"
 	"qfw/util/jy"
 	"qfw/util/mongodb"
@@ -14,8 +13,7 @@ import (
 var Mysql *mysql.Mysql
 
 func init() {
-	DbName = Config.Mongodb.DbName
-	mongodb.InitMongodbPool(Config.Mongodb.Size, Config.Mongodb.Address, DbName)
+	mongodb.InitMongodbPool(Config.Mongodb.Size, Config.Mongodb.Address, Config.Mongodb.DbName)
 	project := mongoutil.PoolConfig{
 		Alias: Config.ProjectMongodb.Alias,
 		Addr:  Config.ProjectMongodb.Address,

+ 3 - 0
src/jfw/modules/pushsubscribe/src/push/util/entity.go

@@ -5,11 +5,14 @@ import (
 	. "public"
 	. "push/config"
 	"qfw/util"
+	"regexp"
 	"strings"
 
 	"github.com/donnie4w/go-logger/logger"
 )
 
+var Re = regexp.MustCompile("<[^>]+>([^<]+)?<[^>]+>")
+
 //推送返回结果
 type PushResult struct {
 	IsVipTempSave bool

+ 2 - 10
src/jfw/modules/pushsubscribe/src/push/util/util.go

@@ -12,7 +12,6 @@ import (
 	"time"
 
 	"github.com/donnie4w/go-logger/logger"
-	"gopkg.in/mgo.v2/bson"
 )
 
 var SavePool chan bool
@@ -20,13 +19,6 @@ var SavePool chan bool
 func init() {
 	SavePool = make(chan bool, Config.SavePoolSize)
 }
-func ToObjectIds(ids []string) []bson.ObjectId {
-	_ids := []bson.ObjectId{}
-	for _, v := range ids {
-		_ids = append(_ids, bson.ObjectIdHex(v))
-	}
-	return _ids
-}
 func ToSortList(list interface{}) *SortList {
 	sl := make(SortList, 0)
 	if list == nil {
@@ -99,7 +91,7 @@ func GetPushDatas(taskType, batchIndex int, collection string, startId *string,
 	i := 0
 	sess := mongodb.GetMgoConn()
 	defer mongodb.DestoryMongoConn(sess)
-	it := sess.DB(DbName).C(collection).Find(query).Sort("_id").Iter()
+	it := sess.DB(Config.Mongodb.DbName).C(collection).Find(query).Sort("_id").Iter()
 	for temp := make(map[string]interface{}); it.Next(&temp); {
 		i++
 		*startId = util.BsonIdToSId(temp["_id"])
@@ -290,7 +282,7 @@ func SaveToPushsubscribe(isVipUser, isProjectInfo bool, userId string, matchInfo
 	sevenDayCache, err := jy.SubscribePush.GetSevenDayCache(userId)
 	if err == nil && sevenDayCache != nil && len(sevenDayCache) > 0 {
 		for _, v := range sevenDayCache {
-			if v.Ca_date > unix-SevenDay {
+			if v != nil && v.Ca_date > unix-SevenDay {
 				subPush_datas = append(subPush_datas, v)
 			}
 		}

+ 43 - 0
src/jfw/modules/pushsubscribe/src/report/config.json

@@ -0,0 +1,43 @@
+{
+	"jianyuDomain":"https://web-jydev-wcj.jianyu360.cn",
+	"weixinRpcServer":"127.0.0.1:8083",
+	"elasticPoolSize":1,
+	"elasticSearch":"http://192.168.3.128:9800",
+	"mongodb":{
+		"dbName":"qfw",
+		"address":"192.168.3.128:27080",
+		"size":5
+	},
+	"mysql":{
+        "dbName":"jianyu",
+        "address":"192.168.3.11:3366",
+        "userName":"root",
+        "passWord":"Topnet123",
+		"maxOpenConns": 60,
+		"maxIdleConns": 10
+    },
+	"pushMonth":2,
+	"pushWeek":"Tuesday",
+	"pushTime":"7:00",
+	"statisticTime":"1:30",
+	"pushPoolSize":10,
+	"statisticPoolSize":10,
+	"testids":["5d81c5a525ef8723ac0036f9"],
+	"statisticBatch":100,
+	"pushBatch":100,
+	"wxTplMsg":{
+		"id": "uOIrT3SBSfVFEY0Ybm6wyEKIiUwAytb9YUlLOqv7uSw",
+		"first":{
+			"value":"VIP订阅用户,本期数据报告已生成,快来查看吧!"
+		},
+		"keyword1": {
+			"value":"数据报告(VIP订阅)"
+		},
+		"keyword2": {
+			"value":"%s-%s"
+		},
+		"remark": {
+			"value":"点击查看详情!"
+		}
+	}
+}

+ 54 - 0
src/jfw/modules/pushsubscribe/src/report/config/config.go

@@ -0,0 +1,54 @@
+package config
+
+import (
+	"qfw/util"
+	qrpc "qfw/util/rpc"
+)
+
+type config struct {
+	JianyuDomain    string `json:"jianyuDomain"`
+	WeixinRpcServer string `json:"weixinRpcServer"`
+	ElasticPoolSize int    `json:"elasticPoolSize"`
+	ElasticSearch   string `json:"elasticSearch"`
+	Mongodb         struct {
+		Alias    string `json:"alias"`
+		DbName   string `json:"dbName"`
+		CollName string `json:"collName"`
+		Address  string `json:"address"`
+		Size     int    `json:"size"`
+	} `json:"mongodb"`
+	Mysql struct {
+		DbName       string
+		Address      string
+		UserName     string
+		PassWord     string
+		MaxOpenConns int
+		MaxIdleConns int
+	} `json:"mysql"`
+	PushMonth         int       `json:"pushMonth"`
+	PushWeek          string    `json:"pushWeek"`
+	PushTime          string    `json:"pushTime"`
+	StatisticTime     string    `json:"statisticTime"`
+	PushPoolSize      int       `json:"pushPoolSize"`
+	StatisticPoolSize int       `json:"statisticPoolSize"`
+	TestIds           []string  `json:"testids"`
+	StatisticBatch    int       `json:"statisticBatch"`
+	PushBatch         int       `json:"pushBatch"`
+	WxTplMsg          *WxTplMsg `json:"wxTplMsg"`
+}
+
+type WxTplMsg struct {
+	Id       string
+	First    *qrpc.TmplItem
+	Keyword1 *qrpc.TmplItem
+	Keyword2 *qrpc.TmplItem
+	Keyword3 *qrpc.TmplItem
+	Keyword4 *qrpc.TmplItem
+	Remark   *qrpc.TmplItem
+}
+
+var Config *config
+
+func init() {
+	util.ReadConfig(&Config)
+}

+ 9 - 0
src/jfw/modules/pushsubscribe/src/report/job/jobs.go

@@ -0,0 +1,9 @@
+package job
+
+var Jobs = struct {
+	Statistic *StatisticJob
+	Push      *PushJob
+}{
+	Statistic: &StatisticJob{},
+	Push:      &PushJob{},
+}

+ 147 - 0
src/jfw/modules/pushsubscribe/src/report/job/pushjob.go

@@ -0,0 +1,147 @@
+package job
+
+import (
+	"fmt"
+	. "public"
+	"qfw/util"
+	"qfw/util/mongodb"
+	qrpc "qfw/util/rpc"
+	. "report/config"
+	"strconv"
+	"sync"
+	"time"
+
+	"github.com/donnie4w/go-logger/logger"
+	"gopkg.in/mgo.v2/bson"
+)
+
+type PushJob struct {
+}
+
+func (p *PushJob) Execute(startDate, endDate int64) {
+	defer util.Catch()
+	logger.Info("开始推送。。。", startDate, endDate)
+	batchIndex := 0
+	startId := ""
+	//
+	pool := make(chan bool, Config.PushPoolSize)
+	wait := &sync.WaitGroup{}
+	for {
+		batchIndex++
+		isBreak, users := p.OnceBatch(batchIndex, startDate, endDate, &startId)
+		for _, temp := range *users {
+			pool <- true
+			wait.Add(1)
+			go func(v map[string]interface{}) {
+				defer func() {
+					util.Catch()
+					<-pool
+					wait.Done()
+				}()
+				sess := mongodb.GetMgoConn()
+				if sess == nil {
+					logger.Error("获取mongodb连接错误")
+					return
+				}
+				defer mongodb.DestoryMongoConn(sess)
+				userId, _ := v["userid"].(string)
+				logger.Info("开始推送用户", userId)
+				var user map[string]interface{}
+				sess.DB(Config.Mongodb.DbName).C(User).FindId(bson.ObjectIdHex(userId)).Select(map[string]interface{}{
+					"_id":           1,
+					"s_m_openid":    1,
+					"s_jpushid":     1,
+					"s_opushid":     1,
+					"i_ispush":      1,
+					"s_appponetype": 1,
+				}).One(&user)
+				s_m_openid, _ := user["s_m_openid"].(string)
+				isPushWx := util.IntAllDef(user["i_ispush"], 1)
+				//jpushid, _ := user["s_jpushid"].(string)
+				//opushid, _ := user["s_opushid"].(string)
+				//phoneType, _ := user["s_appponetype"].(string)
+				wxPushOk := false
+				start := util.FormatDateByInt64(&startDate, "2006年01月02日")
+				end := util.FormatDateByInt64(&endDate, "2006年01月02日")
+				if isPushWx == 1 && s_m_openid != "" {
+					tmplData := map[string]*qrpc.TmplItem{
+						"first": &qrpc.TmplItem{
+							Value: Config.WxTplMsg.First.Value,
+						},
+						"keyword1": &qrpc.TmplItem{
+							Value: Config.WxTplMsg.Keyword1.Value,
+						},
+						"keyword2": &qrpc.TmplItem{
+							Value: fmt.Sprintf(Config.WxTplMsg.Keyword2.Value, start, end),
+						},
+						"remark": &qrpc.TmplItem{
+							Value: Config.WxTplMsg.Remark.Value,
+						},
+					}
+					wxPushOk, _ = qrpc.WxSendTmplMsg(Config.WeixinRpcServer, &qrpc.WxTmplMsg{
+						OpenId:   s_m_openid,
+						TplId:    Config.WxTplMsg.Id,
+						TmplData: tmplData,
+						Url:      Config.JianyuDomain + "/front/sess/" + Se.EncodeString(s_m_openid+",uid,"+strconv.Itoa(int(time.Now().Unix()))+",vipreport") + "__" + fmt.Sprint(startDate) + "__" + fmt.Sprint(endDate) + "__" + fmt.Sprint(util.IntAll(v["pushcount"])),
+					})
+					logger.Info("微信推送", userId, wxPushOk)
+				}
+				if wxPushOk {
+					sess.DB(Config.Mongodb.DbName).C(Pushspace_statistic).UpdateId(v["_id"], map[string]interface{}{
+						"$set": map[string]interface{}{
+							"unread":   1,
+							"tip":      1,
+							"ispush":   1,
+							"pushtime": time.Now().Unix(),
+						},
+					})
+				}
+			}(temp)
+		}
+		if isBreak {
+			break
+		}
+	}
+	wait.Wait()
+	logger.Info("推送结束。。。")
+}
+
+//分批次加载
+func (p *PushJob) OnceBatch(batchIndex int, startDate, endDate int64, startId *string) (bool, *[]map[string]interface{}) {
+	query := map[string]interface{}{
+		"ispush":    0,
+		"startdate": startDate,
+		"enddate":   endDate,
+	}
+	if len(Config.TestIds) > 0 {
+		query["userid"] = map[string]interface{}{
+			"$in": Config.TestIds,
+		}
+	}
+	if *startId != "" {
+		query["_id"] = map[string]interface{}{
+			"$gt": bson.ObjectIdHex(*startId),
+		}
+	}
+	logger.Info("开始加载第", batchIndex, "批推送用户", query)
+	users := []map[string]interface{}{}
+	i := 0
+	sess := mongodb.GetMgoConn()
+	defer mongodb.DestoryMongoConn(sess)
+	it := sess.DB(Config.Mongodb.DbName).C(Pushspace_statistic).Find(query).Select(map[string]interface{}{
+		"_id":       1,
+		"userid":    1,
+		"pushcount": 1,
+	}).Sort("_id").Iter()
+	for temp := make(map[string]interface{}); it.Next(&temp); {
+		i++
+		*startId = util.BsonIdToSId(temp["_id"])
+		users = append(users, temp)
+		temp = make(map[string]interface{})
+		if i == Config.StatisticBatch {
+			break
+		}
+	}
+	logger.Info("第", batchIndex, "推送用户加载结束", *startId)
+	return i < Config.StatisticBatch, &users
+}

+ 349 - 0
src/jfw/modules/pushsubscribe/src/report/job/statisticjob.go

@@ -0,0 +1,349 @@
+package job
+
+import (
+	"fmt"
+	. "public"
+	"qfw/util"
+	"qfw/util/elastic"
+	"qfw/util/mongodb"
+	. "report/config"
+	. "report/util"
+	"strings"
+	"sync"
+	"time"
+
+	"github.com/donnie4w/go-logger/logger"
+	mgo "gopkg.in/mgo.v2"
+	"gopkg.in/mgo.v2/bson"
+)
+
+const (
+	ProjectQuery  = `{"query":{"filtered":{"filter":{"terms":{"list.infoid":[%s]}}}},"_source":["list.subtype","list.toptype"],"from":0,"size":%d}`
+	batchIdLength = 20
+)
+
+//时间都是,没有
+type StatisticJob struct {
+	month_start      int64 //今天所在月份开始时间,精确到年月日
+	month_end        int64 //今天所在月份结束时间,精确到年月日
+	week_start       int64 //今天所在周开始时间,精确到年月日
+	week_end         int64 //今天所在周结束时间,精确到年月日
+	today_start      int64 //今天开始时间,精确到年月日
+	today_end        int64 //今天结束时间,精确到年月日
+	today_end_ymdhms int64 //今天结束时间,精确到年月日时分秒,查询mysql推送历史用到
+}
+
+func (s *StatisticJob) Execute(now time.Time) {
+	defer util.Catch()
+	s.today_start, s.today_end, s.today_end_ymdhms = s.GetToday(now)
+	s.week_start, s.week_end = s.GetWeek(now)
+	s.month_start, s.month_end = s.GetMonth(now)
+	logger.Info("开始统计。。。", util.FormatDate(&now, util.Date_yyyyMMdd))
+	batchIndex := 0
+	startId := ""
+	//
+	pool := make(chan bool, Config.StatisticPoolSize)
+	wait := &sync.WaitGroup{}
+	for {
+		batchIndex++
+		isBreak, users := s.OnceBatch(batchIndex, &startId)
+		for _, temp := range *users {
+			pool <- true
+			wait.Add(1)
+			go func(v map[string]interface{}) {
+				defer func() {
+					util.Catch()
+					<-pool
+					wait.Done()
+				}()
+				if s.Filter(now, util.Int64All(v["l_vip_starttime"])) {
+					return
+				}
+				userId := util.BsonIdToSId(v["_id"])
+				logger.Info("开始统计用户", "userId", userId)
+				todayPushCount := Mysql.CountBySql("select count(1) from pushsubscribe where userid=? and date>=? and date<=? and isvip=1", userId, s.today_start, s.today_end_ymdhms)
+				//toptype
+				toptype := Mysql.SelectBySql("select b.name,sum(1) as sum from (select if(toptype is null,5,toptype) as toptype from pushsubscribe where userid=? and date>=? and date<=? and isvip=1) as a inner join infotype b on (a.toptype=b.id) group by a.toptype", userId, s.today_start, s.today_end_ymdhms)
+				todayToptype := map[string]int{}
+				for _, v := range *toptype {
+					todayToptype[util.ObjToString(v["name"])] = util.IntAll(v["sum"])
+				}
+				//subtype统计
+				subtype := Mysql.SelectBySql("select b.name,sum(1) as sum from (select if(subtype is null,15,subtype) as subtype from pushsubscribe where userid=? and date>=? and date<=? and toptype=1 and isvip=1) as a inner join infotype b on (a.subtype=b.id) group by a.subtype", userId, s.today_start, s.today_end_ymdhms)
+				todaySubtype := map[string]int{}
+				for _, v := range *subtype {
+					todaySubtype[util.ObjToString(v["name"])] = util.IntAll(v["sum"])
+				}
+				datas := Mysql.SelectBySql("select infoid from pushsubscribe where userid=? and date>=? and date<=? and toptype=4 and isvip=1", userId, s.today_start, s.today_end_ymdhms)
+				if datas != nil {
+					projectSubtypes := s.SearchProject(datas)
+					for _, v := range projectSubtypes {
+						todaySubtype[v] = todaySubtype[v] + 1
+					}
+				}
+				//关键词统计
+				matchkeys := Mysql.SelectBySql("select a.matchkeys,sum(1) as sum from (select matchkeys from pushsubscribe where userid=? and date>=? and date<=? and isvip=1 and matchkeys is not null) as a group by a.matchkeys", userId, s.today_start, s.today_end_ymdhms)
+				todayMatchkeys := map[string]int{}
+				for _, v := range *matchkeys {
+					todayMatchkeys[util.ObjToString(v["matchkeys"])] = util.IntAll(v["sum"])
+				}
+				//省统计
+				area := Mysql.SelectBySql("select b.name,sum(1) as sum from pushsubscribe as a inner join province b on (a.area=b.id) where a.userid=? and a.date>=? and a.date<=? and isvip=1 group by a.area", userId, s.today_start, s.today_end_ymdhms)
+				todayArea := map[string]int{}
+				for _, v := range *area {
+					todayArea[util.ObjToString(v["name"])] = util.IntAll(v["sum"])
+				}
+				//市统计
+				city := Mysql.SelectBySql("select d.name as area,c.name as city,c.sum from (select a.area,b.name,sum(1) as sum from pushsubscribe as a inner join province b on (a.city=b.id) where a.userid=? and a.date>=? and a.date<=? and isvip=1 group by a.city,a.area) as c inner join province d on (c.area=d.id)", userId, s.today_start, s.today_end_ymdhms)
+				todayCity := map[string]map[string]int{}
+				for _, v := range *city {
+					if todayCity[util.ObjToString(v["area"])] == nil {
+						todayCity[util.ObjToString(v["area"])] = map[string]int{}
+					}
+					todayCity[util.ObjToString(v["area"])][util.ObjToString(v["city"])] = util.IntAll(v["sum"])
+				}
+				//天
+				sess := mongodb.GetMgoConn()
+				if sess == nil {
+					logger.Error("获取mongodb连接错误")
+					return
+				}
+				defer mongodb.DestoryMongoConn(sess)
+				_, err := sess.DB(Config.Mongodb.DbName).C(Pushspace_statistic).Upsert(map[string]interface{}{
+					"userid":    userId,
+					"startdate": s.today_start,
+					"enddate":   s.today_end,
+					"type":      1,
+				}, map[string]interface{}{
+					"$set": map[string]interface{}{
+						"dateym":           s.GetDateym(s.today_end),
+						"createtime":       time.Now().Unix(),
+						"pushcount":        todayPushCount,
+						"toptype":          todayToptype,
+						"subtype_zhaobiao": todaySubtype,
+						"matchkeys":        todayMatchkeys,
+						"area":             todayArea,
+						"city":             todayCity,
+					},
+				})
+				if err != nil {
+					logger.Error(userId, "更新出错", err)
+				}
+				//周
+				s.Upsert(sess, 2, userId, s.week_start, s.week_end, todayPushCount, todayToptype, todaySubtype, todayMatchkeys, todayArea, todayCity)
+				//月
+				s.Upsert(sess, 3, userId, s.month_start, s.month_end, todayPushCount, todayToptype, todaySubtype, todayMatchkeys, todayArea, todayCity)
+			}(temp)
+		}
+		if isBreak {
+			break
+		}
+	}
+	wait.Wait()
+	logger.Info("统计结束。。。")
+}
+
+//过滤用户,非vip时间内,不出报告
+func (s *StatisticJob) Filter(now time.Time, l_vip_starttime int64) bool {
+	t1 := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, time.Local)
+	vip_starttime := time.Unix(l_vip_starttime, 0)
+	t2 := time.Date(vip_starttime.Year(), vip_starttime.Month(), vip_starttime.Day(), 0, 0, 0, 0, time.Local)
+	if t1.Before(t2) {
+		return true
+	}
+	return false
+}
+
+//分批次加载
+func (s *StatisticJob) OnceBatch(batchIndex int, startId *string) (bool, *[]map[string]interface{}) {
+	query := map[string]interface{}{
+		"i_vip_status": map[string]interface{}{
+			"$in": []int{1, 2},
+		},
+	}
+	if len(Config.TestIds) > 0 {
+		query["_id"] = map[string]interface{}{
+			"$in": ToObjectIds(Config.TestIds),
+		}
+	}
+	if *startId != "" {
+		query["_id"] = map[string]interface{}{
+			"$gt": bson.ObjectIdHex(*startId),
+		}
+	}
+	logger.Info("开始加载第", batchIndex, "批统计用户", query)
+	users := []map[string]interface{}{}
+	i := 0
+	sess := mongodb.GetMgoConn()
+	defer mongodb.DestoryMongoConn(sess)
+	it := sess.DB(Config.Mongodb.DbName).C(User).Find(query).Select(map[string]interface{}{
+		"_id":             1,
+		"l_vip_starttime": 1,
+	}).Sort("_id").Iter()
+	for temp := make(map[string]interface{}); it.Next(&temp); {
+		i++
+		*startId = util.BsonIdToSId(temp["_id"])
+		users = append(users, temp)
+		temp = make(map[string]interface{})
+		if i == Config.StatisticBatch {
+			break
+		}
+	}
+	logger.Info("第", batchIndex, "批统计用户加载结束", *startId)
+	return i < Config.StatisticBatch, &users
+}
+
+//获取月
+func (s *StatisticJob) GetDateym(unix int64) int {
+	return util.IntAll(util.FormatDateByInt64(&unix, "200601"))
+}
+
+//当前日的开始和结束时间
+func (s *StatisticJob) GetToday(now time.Time) (int64, int64, int64) {
+	start := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, time.Local)
+	end := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, time.Local)
+	end_ymdhms := time.Date(now.Year(), now.Month(), now.Day(), 23, 59, 59, 0, time.Local)
+	return start.Unix(), end.Unix(), end_ymdhms.Unix()
+}
+
+//当前周的开始和结束时间
+func (s *StatisticJob) GetWeek(now time.Time) (int64, int64) {
+	week := WeekNum[now.Weekday().String()]
+	start := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, time.Local)
+	if s := week - 1; s > 0 {
+		start = start.AddDate(0, 0, -s)
+	}
+	end := start.AddDate(0, 0, 6)
+	return start.Unix(), end.Unix()
+}
+
+//当前月的开始和结束时间
+func (s *StatisticJob) GetMonth(now time.Time) (int64, int64) {
+	start := time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, time.Local)
+	end := start.AddDate(0, 1, 0).AddDate(0, 0, -1)
+	return start.Unix(), end.Unix()
+}
+
+//新增或者更新库中月、周的数据
+func (s *StatisticJob) Upsert(session *mgo.Session, tp int, userId string, start, end, todayPushCount int64, todayToptype, todaySubtype, todayMatchkeys, todayArea map[string]int, todayCity map[string]map[string]int) {
+	coll := session.DB(Config.Mongodb.DbName).C(Pushspace_statistic)
+	var monthObj map[string]interface{}
+	coll.Find(map[string]interface{}{
+		"type":      tp,
+		"userid":    userId,
+		"startdate": start,
+		"enddate":   end,
+	}).Select(map[string]interface{}{
+		"_id":              1,
+		"pushcount":        1,
+		"matchkeys":        1,
+		"toptype":          1,
+		"subtype_zhaobiao": 1,
+		"area":             1,
+		"city":             1,
+	}).One(&monthObj)
+	if monthObj == nil {
+		err := coll.Insert(map[string]interface{}{
+			"type":             tp,
+			"userid":           userId,
+			"startdate":        start,
+			"enddate":          end,
+			"pushcount":        todayPushCount,
+			"toptype":          todayToptype,
+			"subtype_zhaobiao": todaySubtype,
+			"matchkeys":        todayMatchkeys,
+			"area":             todayArea,
+			"city":             todayCity,
+			"createtime":       time.Now().Unix(),
+			"ispush":           0,
+			"dateym":           s.GetDateym(end),
+		})
+		if err != nil {
+			logger.Error(userId, "新增出错", err)
+		}
+	} else {
+		toptype, _ := monthObj["toptype"].(map[string]interface{})
+		for k, v := range todayToptype {
+			toptype[k] = util.IntAll(toptype[k]) + v
+		}
+		subtype, _ := monthObj["subtype_zhaobiao"].(map[string]interface{})
+		for k, v := range todaySubtype {
+			subtype[k] = util.IntAll(subtype[k]) + v
+		}
+		matchkeys, _ := monthObj["matchkeys"].(map[string]interface{})
+		for k, v := range todayMatchkeys {
+			matchkeys[k] = util.IntAll(matchkeys[k]) + v
+		}
+		area, _ := monthObj["area"].(map[string]interface{})
+		for k, v := range todayArea {
+			area[k] = util.IntAll(area[k]) + v
+		}
+		city, _ := monthObj["city"].(map[string]interface{})
+		for k, v := range todayCity {
+			vm, _ := city[k].(map[string]interface{})
+			if vm == nil {
+				vm = map[string]interface{}{}
+			}
+			for kk, vv := range v {
+				vm[kk] = util.IntAll(vm[kk]) + vv
+			}
+			city[k] = vm
+		}
+		err := coll.UpdateId(monthObj["_id"], map[string]interface{}{
+			"$set": map[string]interface{}{
+				"pushcount":        util.IntAll(monthObj["pushcount"]) + int(todayPushCount),
+				"toptype":          toptype,
+				"subtype_zhaobiao": subtype,
+				"matchkeys":        matchkeys,
+				"area":             area,
+				"city":             city,
+				"updatetime":       time.Now().Unix(),
+			},
+		})
+		if err != nil {
+			logger.Error(userId, "更新出错", err)
+		}
+	}
+}
+
+//如果是中标的,去项目表里面找改信息的招标类型
+func (s *StatisticJob) SearchProject(datas *[]map[string]interface{}) []string {
+	result := []string{}
+	batchIds := []string{}
+	for _, data := range *datas {
+		batchIds = append(batchIds, util.ObjToString(data["infoid"]))
+		if len(batchIds) == batchIdLength {
+			result = append(result, s.projectSubtypes(batchIds)...)
+			batchIds = []string{}
+		}
+	}
+	if len(batchIds) > 0 {
+		result = append(result, s.projectSubtypes(batchIds)...)
+	}
+	return result
+}
+
+func (s *StatisticJob) projectSubtypes(ids []string) []string {
+	result := []string{}
+	query := fmt.Sprintf(ProjectQuery, `"`+strings.Join(ids, `","`)+`"`, batchIdLength)
+	list := elastic.Get(Projectset, Projectset, query)
+	if list == nil {
+		return result
+	}
+	for _, v := range *list {
+		array, _ := v["list"].([]interface{})
+		for _, vv := range array {
+			vvMap, _ := vv.(map[string]interface{})
+			toptype, _ := vvMap["toptype"].(string)
+			subtype, _ := vvMap["subtype"].(string)
+			if subtype == "" {
+				subtype = "其它"
+			}
+			if toptype == "招标" && subtype != "" {
+				result = append(result, subtype)
+				break
+			}
+		}
+	}
+	return result
+}

+ 56 - 0
src/jfw/modules/pushsubscribe/src/report/job/timetask.go

@@ -0,0 +1,56 @@
+package job
+
+import (
+	"log"
+	. "public"
+	"qfw/util"
+	. "report/config"
+	"strings"
+	"time"
+)
+
+type TimeTask struct{}
+
+func (t *TimeTask) Run() {
+	go t.crontab(Config.PushTime, func() {
+		isPushMonth := time.Now().Day() == Config.PushMonth
+		isPushWeek := strings.ToUpper(time.Now().Weekday().String()) == strings.ToUpper(Config.PushWeek)
+		if isPushMonth {
+			now := time.Now().AddDate(0, -1, 0)
+			startDate := time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, time.Local)
+			endDate := startDate.AddDate(0, 1, -1)
+			Jobs.Push.Execute(startDate.Unix(), endDate.Unix())
+		} else if isPushWeek {
+			endDate := time.Now().AddDate(0, 0, -WeekNum[time.Now().Weekday().String()])
+			endDate = time.Date(endDate.Year(), endDate.Month(), endDate.Day(), 0, 0, 0, 0, time.Local)
+			startDate := endDate.AddDate(0, 0, -6)
+			Jobs.Push.Execute(startDate.Unix(), endDate.Unix())
+		}
+	})
+	go t.crontab(Config.StatisticTime, func() {
+		Jobs.Statistic.Execute(time.Now().AddDate(0, 0, -1))
+	})
+}
+
+func (t *TimeTask) crontab(tm string, f func()) {
+	h_m := strings.Split(tm, ":")
+	if len(h_m) == 2 {
+		now := time.Now()
+		newDate := time.Date(now.Year(), now.Month(), now.Day(), util.IntAll(h_m[0]), util.IntAll(h_m[1]), 0, 0, time.Local)
+		if newDate.Before(now) {
+			newDate = newDate.AddDate(0, 0, 1)
+		}
+		sub := newDate.Sub(now)
+		log.Println("start", tm, "after", sub)
+		timer := time.NewTimer(sub)
+		for {
+			select {
+			case <-timer.C:
+				go f()
+				timer.Reset(time.Hour * 24)
+			}
+		}
+	} else {
+		log.Fatalln("crontab", tm)
+	}
+}

+ 42 - 0
src/jfw/modules/pushsubscribe/src/report/main.go

@@ -0,0 +1,42 @@
+package main
+
+import (
+	"flag"
+	"log"
+	"report/job"
+	"time"
+
+	"github.com/donnie4w/go-logger/logger"
+)
+
+func main() {
+	m := flag.Int("m", 0, "1-统计今天 2-指定时间段统计 3-指定时间段推送")
+	s := flag.Int64("s", 0, "开始时间")
+	e := flag.Int64("e", 0, "结束时间")
+	flag.Parse()
+	if (*m == 2 || *m == 3) && (*s == 0 || *e == 0) {
+		log.Fatalln("缺少-s或者-e参数")
+	}
+	log.Println("订阅报告程序启动。。。")
+	logger.SetConsole(false)
+	logger.SetRollingDaily("./logs", "report.log")
+	if *m == 1 {
+		job.Jobs.Statistic.Execute(time.Now())
+	} else if *m == 2 {
+		start := time.Unix(*s, 0)
+		end := time.Unix(*e, 0)
+		for {
+			if start.After(end) {
+				break
+			}
+			job.Jobs.Statistic.Execute(start)
+			start = start.AddDate(0, 0, 1)
+		}
+	} else if *m == 3 {
+		job.Jobs.Push.Execute(*s, *e)
+	}
+	if *m == 0 {
+		(&job.TimeTask{}).Run()
+		<-chan bool(nil)
+	}
+}

+ 27 - 0
src/jfw/modules/pushsubscribe/src/report/util/db.go

@@ -0,0 +1,27 @@
+package util
+
+import (
+	"log"
+	"qfw/util/elastic"
+	"qfw/util/mongodb"
+	"qfw/util/mysql"
+	. "report/config"
+)
+
+var Mysql *mysql.Mysql
+
+func init() {
+	elastic.InitElasticSize(Config.ElasticSearch, Config.ElasticPoolSize)
+	mongodb.InitMongodbPool(Config.Mongodb.Size, Config.Mongodb.Address, Config.Mongodb.DbName)
+	log.Println("mongodb初始化完成!")
+	Mysql = &mysql.Mysql{
+		DBName:       Config.Mysql.DbName,
+		Address:      Config.Mysql.Address,
+		UserName:     Config.Mysql.UserName,
+		PassWord:     Config.Mysql.PassWord,
+		MaxOpenConns: Config.Mysql.MaxOpenConns,
+		MaxIdleConns: Config.Mysql.MaxIdleConns,
+	}
+	Mysql.Init()
+	log.Println("mysql初始化完成!")
+}

+ 3 - 2
src/jfw/modules/subscribepay/src/a/init.go

@@ -1,6 +1,7 @@
 package initxweb
 
 import (
+	"report"
 	"service"
 	"time"
 
@@ -28,9 +29,9 @@ func init() {
 	xweb.AddRouter("/subscribepay", &service.EditSub{})          //购买内容修改
 	xweb.AddRouter("/subscribepay", &service.OrderListDetails{}) //订单详情&列表
 	xweb.AddRouter("/subscribepay", &service.RenewUpgrade{})     //续费&升级
-
+	xweb.AddRouter("/subscribepay", &report.Report{})            //订阅报告
 	//p1
-	xweb.AddRouter("/subscribepay", &service.IndexSearch{})     //续费&升级
+	xweb.AddRouter("/subscribepay", &service.IndexSearch{}) //续费&升级
 
 	//数据导出
 	xweb.AddRouter("/jypay", &service.DataExportPayMobile{})

+ 8 - 15
src/jfw/modules/subscribepay/src/config.json

@@ -10,21 +10,6 @@
     "webport": "86",
     "webrpcport": "8600",
     "weixinrpc": "127.0.0.1:8083",
-    "cassandra": {
-        "log": {
-            "host": [
-                "192.168.3.207"
-            ],
-            "size": 5,
-            "port": 9042
-        },
-        "push": {
-            "host": [
-                "192.168.3.207"
-            ],
-            "size": 5
-        }
-    },
     "mysql": {
         "dbName": "jianyu",
         "address": "192.168.3.11:3366",
@@ -40,6 +25,14 @@
         "passWord": "Topnet123",
 		"maxOpenConns":2000,
 		"maxIdleConns":1000
+    },
+	"cassandra": {
+        "push": {
+            "host": [
+                "192.168.3.207"
+            ],
+            "size": 5
+        }
     },
 	"appPushServiceRpc": "127.0.0.1:5566",
     "webdomain": "http://web-jydev-zxl.jianyu360.cn",

+ 2 - 6
src/jfw/modules/subscribepay/src/config/config.go

@@ -18,12 +18,8 @@ type config struct {
 	Webport         string
 	Webrpcport      string
 	Weixinrpc       string
-	Cassandra       struct {
-		Host []string
-		Size int
-		Port int
-	}
-	Mysql struct {
+	Cassandra       map[string]interface{}
+	Mysql           struct {
 		DbName       string
 		Address      string
 		UserName     string

+ 406 - 0
src/jfw/modules/subscribepay/src/report/report.go

@@ -0,0 +1,406 @@
+package report
+
+import (
+	"encoding/json"
+	"fmt"
+	qutil "qfw/util"
+	"qfw/util/jy"
+	"sort"
+	"strings"
+	"time"
+	"util"
+
+	"github.com/go-xweb/xweb"
+)
+
+var (
+	subtype_zhaobiao_mapping = map[string]string{
+		"单一": "单一来源",
+		"招标": "公开招标",
+		"竞价": "公开竞价",
+		"竞谈": "竞争性谈判",
+		"询价": "询价采购",
+		"邀标": "邀请招标",
+	}
+	toptype_mapping = map[string]string{
+		"其它": "其他信息",
+		"招标": "招标公告",
+		"结果": "招标结果",
+		"预告": "招标预告",
+		"拟建": "拟建项目",
+	}
+)
+
+//vip订阅报告
+type Report struct {
+	*xweb.Action
+	index     xweb.Mapper `xweb:"/report/index"`
+	detail    xweb.Mapper `xweb:"/report/detail"`
+	tip       xweb.Mapper `xweb:"/report/tip"`
+	tipover   xweb.Mapper `xweb:"/report/tipover"`
+	wxtplmsg  xweb.Mapper `xweb:"/report/wxtplmsg"`
+	starttime xweb.Mapper `xweb:"/report/starttime"`
+}
+
+func (r *Report) Index() {
+	ym, _ := r.GetInteger("ym")
+	result := map[string]interface{}{}
+	userId, _ := r.GetSession("userId").(string)
+	list, ok := util.MQFW.Find("pushspace_statistic", map[string]interface{}{
+		"userid": userId,
+		"dateym": ym,
+		"type": map[string]interface{}{
+			"$in": []int{2, 3},
+		},
+	}, `{"startdate":-1}`, `{"startdate":1,"enddate":1,"type":1,"pushcount":1,"pushtime":1,"unread":1}`, false, -1, -1)
+	if ok && list != nil {
+		weeks := []map[string]interface{}{}
+		for _, v := range *list {
+			r := map[string]interface{}{
+				"pushtime":  v["pushtime"],
+				"pushcount": v["pushcount"],
+				"unread":    qutil.IntAll(v["unread"]),
+				"startdate": v["startdate"],
+				"enddate":   v["enddate"],
+			}
+			if qutil.IntAll(v["type"]) == 2 {
+				weeks = append(weeks, r)
+			} else if qutil.IntAll(v["type"]) == 3 {
+				result["month"] = r
+			}
+		}
+		if len(weeks) > 0 {
+			result["weeks"] = weeks
+		}
+	}
+	if len(result) == 0 {
+		result = nil
+	}
+	r.ServeJson(result)
+}
+func (r *Report) Detail() {
+	start, _ := r.GetInt("start")
+	end, _ := r.GetInt("end")
+	result := map[string]interface{}{}
+	var types []int
+	if end-start == 518400 { //周
+		types = []int{1, 2}
+	} else if end-start > 518400 { //月
+		types = []int{1, 3}
+	} else {
+		r.ServeJson(result)
+		return
+	}
+	userId, _ := r.GetSession("userId").(string)
+	list, ok := util.MQFW.Find("pushspace_statistic", map[string]interface{}{
+		"userid": userId,
+		"startdate": map[string]interface{}{
+			"$gte": start,
+		},
+		"enddate": map[string]interface{}{
+			"$lte": end,
+		},
+		"type": map[string]interface{}{
+			"$in": types,
+		},
+	}, `{"startdate":-1}`, `{"startdate":1,"type":1,"pushcount":1,"matchkeys":1,"subtype_zhaobiao":1,"toptype":1,"area":1,"city":1}`, false, -1, -1)
+	if ok && list != nil {
+		days := []map[string]interface{}{}
+		for _, v := range *list {
+			if qutil.IntAll(v["type"]) == 1 {
+				days = append(days, map[string]interface{}{
+					"pushcount": v["pushcount"],
+					"date":      v["startdate"],
+				})
+			} else {
+				matchkeys, _ := v["matchkeys"].(map[string]interface{})
+				var new_matchkeys ComSorts
+				for kk, vv := range matchkeys {
+					new_matchkeys = append(new_matchkeys, &ComSort{
+						Name:  strings.Split(strings.Split(kk, "+")[0], " ")[0],
+						Count: qutil.IntAll(vv),
+					})
+				}
+				sort.Sort(new_matchkeys)
+				result["matchkeys"] = new_matchkeys
+				subtype_zhaobiao, _ := v["subtype_zhaobiao"].(map[string]interface{})
+				new_subtype_zhaobiao := map[string]int{}
+				for kk, vv := range subtype_zhaobiao_mapping {
+					new_subtype_zhaobiao[vv] = qutil.IntAll(subtype_zhaobiao[kk])
+				}
+				result["subtype_zhaobiao"] = new_subtype_zhaobiao
+				toptype, _ := v["toptype"].(map[string]interface{})
+				new_toptype := map[string]int{}
+				for kk, vv := range toptype_mapping {
+					new_toptype[vv] = qutil.IntAll(toptype[kk])
+				}
+				result["toptype"] = new_toptype
+				area, _ := v["area"].(map[string]interface{})
+				result["area"] = area
+				city, _ := v["city"].(map[string]interface{})
+				result["city"] = formatCity(area, city)
+			}
+		}
+		result["days"] = formatDays(start, end, days)
+	}
+	//
+	subscribe := map[string]interface{}{}
+	subscribe["keys"] = []string{}
+	subscribe["area"] = map[string][]string{}
+	subscribe["industry"] = []string{}
+	result["subscribe"] = subscribe
+	userdata, ok := util.MQFW.FindById("user", userId, `{"s_m_openid":1,"a_m_openid":1,"s_phone":1,"a_mergeorder":1}`)
+	if ok {
+		dateSection := getDateSection(start, end)
+		s_m_openid, _ := (*userdata)["s_m_openid"].(string)
+		a_m_openid, _ := (*userdata)["a_m_openid"].(string)
+		s_phone, _ := (*userdata)["s_phone"].(string)
+		a_mergeorder, _ := (*userdata)["a_mergeorder"].([]interface{})
+		openid := jy.GetOldOpenid(s_m_openid, a_m_openid, s_phone, a_mergeorder)
+		//关注项目
+		follow_project := util.Ca_Push.Search(fmt.Sprintf("select pcode,pname,info from jy_pushproject where id in (%s) and openid='%s' limit 100", dateSection, openid))
+		if follow_project != nil {
+			indexMap := map[string]int{}
+			projects := []map[string]interface{}{}
+			for _, v := range follow_project {
+				projectname := qutil.ObjToString(v["pname"])
+				if projectname == "" {
+					projectname = qutil.ObjToString(v["pcode"])
+				}
+				index, ok := indexMap[projectname]
+				//合并
+				if ok {
+					infos, _ := projects[index]["infos"].([]map[string]interface{})
+					infos = append(infos, formatInfo(qutil.ObjToString(v["info"]))...)
+					projects[index]["infos"] = infos
+				} else {
+					projects = append(projects, map[string]interface{}{
+						"projectname": projectname,
+						"infos":       formatInfo(qutil.ObjToString(v["info"])),
+					})
+					indexMap[projectname] = len(projects) - 1
+				}
+			}
+			result["projects"] = projects
+		}
+		//关注企业
+		follow_ent := util.Ca_Push.Search(fmt.Sprintf("select entname,info from jy_pushent where id in (%s) and openid='%s' limit 100", dateSection, openid))
+		if follow_ent != nil {
+			indexMap := map[string]int{}
+			ents := []map[string]interface{}{}
+			for _, v := range follow_ent {
+				entname := qutil.ObjToString(v["entname"])
+				index, ok := indexMap[entname]
+				//合并
+				if ok {
+					infos, _ := ents[index]["infos"].([]map[string]interface{})
+					infos = append(infos, formatInfo(qutil.ObjToString(v["info"]))...)
+					ents[index]["infos"] = infos
+				} else {
+					ents = append(ents, map[string]interface{}{
+						"entname": entname,
+						"infos":   formatInfo(qutil.ObjToString(v["info"])),
+					})
+					indexMap[entname] = len(ents) - 1
+				}
+			}
+			result["ents"] = ents
+		}
+	}
+	go util.MQFW.Update("pushspace_statistic", map[string]interface{}{
+		"userid":    userId,
+		"startdate": start,
+		"enddate":   end,
+	}, map[string]interface{}{
+		"$set": map[string]interface{}{
+			"unread": 0,
+		},
+	}, false, true)
+	r.ServeJson(result)
+}
+func formatDays(start, end int64, days []map[string]interface{}) []map[string]interface{} {
+	if len(days) == 0 {
+		return days
+	}
+	date := qutil.Int64All(days[len(days)-1]["date"])
+	for {
+		if start < date && date < end {
+			date -= 86400
+			days = append(days, map[string]interface{}{
+				"pushcount": 0,
+				"date":      date,
+			})
+		} else {
+			break
+		}
+	}
+	return days
+}
+
+type AreaCitySort struct {
+	Area  string   `json:"area"`
+	Count int      `json:"count"`
+	Citys ComSorts `json:"citys"`
+}
+
+type AreaCitySorts []*AreaCitySort
+
+func (s AreaCitySorts) Len() int {
+	return len(s)
+}
+
+func (s AreaCitySorts) Less(i, j int) bool {
+	return s[i].Count > s[j].Count
+}
+
+func (s AreaCitySorts) Swap(i, j int) {
+	s[i], s[j] = s[j], s[i]
+}
+
+//
+type ComSort struct {
+	Name  string `json:"name"`
+	Count int    `json:"count"`
+}
+
+type ComSorts []*ComSort
+
+func (s ComSorts) Len() int {
+	return len(s)
+}
+
+func (s ComSorts) Less(i, j int) bool {
+	return s[i].Count > s[j].Count
+}
+
+func (s ComSorts) Swap(i, j int) {
+	s[i], s[j] = s[j], s[i]
+}
+
+func formatCity(area, city map[string]interface{}) AreaCitySorts {
+	areaCitys := AreaCitySorts{}
+	for k, v := range city {
+		countCity := 0
+		citys := ComSorts{}
+		vMap, _ := v.(map[string]interface{})
+		for kk, vv := range vMap {
+			countCity += qutil.IntAll(vv)
+			citys = append(citys, &ComSort{
+				Name:  kk,
+				Count: qutil.IntAll(vv),
+			})
+		}
+		sort.Sort(citys)
+		countArea := qutil.IntAll(area[k])
+		if countArea == 0 {
+			countArea = countCity
+		}
+		areaCitys = append(areaCitys, &AreaCitySort{
+			Area:  k,
+			Count: countArea,
+			Citys: citys,
+		})
+	}
+	sort.Sort(areaCitys)
+	return areaCitys
+}
+
+//
+func formatInfo(text string) []map[string]interface{} {
+	var relationinfo []map[string]interface{}
+	json.Unmarshal([]byte(text), &relationinfo)
+	infos := []map[string]interface{}{}
+	for _, v := range relationinfo {
+		infotype, _ := v["s_subtype"].(string)
+		if infotype == "" {
+			infotype, _ = v["s_toptype"].(string)
+		}
+		if infotype == "" {
+			infotype, _ = v["s_type"].(string)
+			if infotype == "tender" {
+				infotype = "招标"
+			} else if infotype == "bid" {
+				infotype = "中标"
+			}
+		}
+		infos = append(infos, map[string]interface{}{
+			"title":       v["s_title"],
+			"id":          qutil.EncodeArticleId2ByCheck(qutil.ObjToString(v["s_id"])),
+			"publishtime": qutil.Int64All(v["l_publishtime"]),
+			"area":        v["s_province"],
+			"infotype":    infotype,
+		})
+	}
+	return infos
+}
+
+func getDateSection(start, end int64) string {
+	array := []string{}
+	s := time.Unix(start, 0)
+	e := time.Unix(end, 0)
+	for {
+		if !s.Before(e) {
+			break
+		}
+		array = append(array, qutil.FormatDate(&s, qutil.Date_Short_Layout))
+		s = s.AddDate(0, 0, 1)
+	}
+	return `'` + strings.Join(array, `','`) + `'`
+}
+func (r *Report) Tip() {
+	userId, _ := r.GetSession("userId").(string)
+	unread := util.MQFW.Count("pushspace_statistic", map[string]interface{}{
+		"userid": userId,
+		"unread": 1,
+	})
+	list, ok := util.MQFW.Find("pushspace_statistic", map[string]interface{}{
+		"userid": userId,
+		"tip":    1,
+	}, `{"enddate":-1}`, `{"_id":0,"type":1,"startdate":1,"enddate":1,"pushcount":1}`, false, 0, 1)
+	result := map[string]interface{}{
+		"unread": unread,
+	}
+	if ok && list != nil && len(*list) == 1 {
+		result["tip"] = (*list)[0]
+	}
+	r.ServeJson(result)
+}
+func (r *Report) Tipover() {
+	userId, _ := r.GetSession("userId").(string)
+	r.ServeJson(map[string]interface{}{"flag": tipover(userId)})
+}
+
+func tipover(userId string) bool {
+	return util.MQFW.Update("pushspace_statistic", map[string]interface{}{
+		"userid": userId,
+		"tip":    1,
+	}, map[string]interface{}{
+		"$set": map[string]interface{}{
+			"tip": 0,
+		},
+	}, false, true)
+}
+func (r *Report) Wxtplmsg() error {
+	userId, _ := r.GetSession("userId").(string)
+	pushcount, _ := r.GetInteger("pushcount")
+	go tipover(userId)
+	return r.Redirect(fmt.Sprintf("/vipreport/page/reportdetail.html?start=%s&end=%s&pushcount=%d", r.GetString("start"), r.GetString("end"), pushcount))
+}
+
+func (r *Report) Starttime() {
+	userId, _ := r.GetSession("userId").(string)
+	list, _ := util.MQFW.Find("pushspace_statistic", map[string]interface{}{
+		"userid": userId,
+		"type": map[string]interface{}{
+			"$in": []int{2, 3},
+		},
+	}, `{"enddate":1}`, `{"enddate":1,"dateym":1}`, false, 0, 1)
+	start := 0
+	if list != nil && len(*list) == 1 {
+		enddate := qutil.Int64All((*list)[0]["enddate"])
+		if time.Now().After(time.Unix(enddate, 0).AddDate(0, 0, 1)) {
+			start = qutil.IntAll((*list)[0]["dateym"])
+		}
+	}
+	r.ServeJson(start)
+}

+ 9 - 7
src/jfw/modules/subscribepay/src/util/db.go

@@ -2,7 +2,6 @@ package util
 
 import (
 	. "config"
-
 	qutil "qfw/util"
 	"qfw/util/elastic"
 	mg "qfw/util/mongodb"
@@ -14,15 +13,18 @@ import (
 var MQFW mg.MongodbSim
 var Mysql *mysql.Mysql
 var PushMysql *mysql.Mysql
-var Ca_Log = &ca.Cassandra{}
+var Ca_Push = &ca.Cassandra{}
 
 func init() {
 	//初始化cassandra
-	Ca_Log.ViewCacheLen = true
-	Ca_Log.InitCassandra("jianyu",
-		Config.Cassandra.Size,
-		Config.Cassandra.Host,
-		map[string]int{"port": Config.Cassandra.Port},
+	ca_push := Config.Cassandra["push"].(map[string]interface{})
+	Ca_Push.ViewCacheLen = true
+	Ca_Push.InitCassandra("jianyu",
+		qutil.IntAll(ca_push["size"]),
+		qutil.ObjArrToStringArr(ca_push["host"].([]interface{})),
+		map[string]int{
+			"port": qutil.IntAll(ca_push["port"]),
+		},
 	)
 	//初始化elastic
 	elastic.InitElasticSize(

+ 3 - 0
src/web/staticres/css/pc.css

@@ -145,6 +145,9 @@ form{
 	color: #686868;
     border-top-left-radius: 4px;
     border-top-right-radius: 4px;
+    white-space:nowrap; 
+	overflow:hidden; 
+	text-overflow:ellipsis;
 	
 }
 .userInfo .infoList .myorderDiv{

BIN
src/web/staticres/upload/2019/09/18/201909181350298943.jpg


BIN
src/web/staticres/upload/2019/10/16/201910161617098943.jpg


BIN
src/web/staticres/upload/2019/11/13/201911131709528943.jpg


+ 21 - 25
src/web/staticres/vipsubscribe/css/subscribe_list.css

@@ -108,10 +108,9 @@
 .free7days_pic,
 .noble_vip_pic {
   display: inline-block;
-  margin-right: .2rem;
-  padding-left: .4rem;
-  height: .4rem;
-  line-height: normal;
+  margin-right: 5px;
+  padding-right: 20px;
+  height: 22px;
   background: url(../image/v_icon.png) no-repeat left center;
   background-size: contain;
 }
@@ -119,12 +118,12 @@
 .free7days_pic:after {
   content: '试用7天';
   position: relative;
-  top: -0.03rem;
-  left: .05rem;
+  top: 0px;
+  left: 23px;
   display: inline-block;
-  padding: 0 .04rem;
+  padding: 0 1px;
   line-height: normal;
-  font-size: 0.18rem;
+  font-size: 12px;
   color: #fff;
   text-align: center;
   background-color: #CFAD89;
@@ -133,8 +132,8 @@
 
 .vip_banner .box {
   width: 100%;
-  height: .94rem;
-  padding: 0 .3rem;
+  height: 45px;
+  padding: 0 15px;
   box-sizing: border-box;
   background: url(../image/curve.png) no-repeat center center #34355A;
   background-size: 100% 100%;
@@ -159,11 +158,10 @@ font-weight: bold;
 
 .filter_tab {
   position: relative;
-  height: .88rem;
-  line-height: .88rem;
-  padding: 0 .3rem;
+  padding: 10px 8px;
   background: #fff;
-      border-bottom: 1px solid #E6E6E6;
+  border-bottom: 1px solid #E6E6E6;
+  font-size: 15px;
 }
 
 /*.filter_tab:after {
@@ -183,14 +181,13 @@ font-weight: bold;
 }
 
 .filter_tab .tab_left .time {
-  margin-right: .25rem;
+  margin-right: 20px;
 }
 
 .filter_tab .tab_left .time_box,
 .filter_tab .tab_left .area_box {
-  margin-right: .3rem;
+  margin-right: 5px;
   color: #686868;
-  font-size: .28rem;
 }
 
 .filter_tab .tab_left .time_box i,
@@ -201,34 +198,33 @@ font-weight: bold;
 }
 
 .filter_tab .tab_right .normal_set_box {
-  font-size: .28rem;
+  font-size: 15px;
   color: #1D1D1D;
   height: 100%;
   box-sizing: border-box;
 }
 
 .filter_tab .tab_right .normal_set_box i {
-  margin-right: .16rem;
-  font-size: .4rem;
+  margin-right: 5px;
+  font-size: 22px;
   color: #707070;
 }
 
 .filter_tab .tab_right .vip_set_box {
   position: relative;
-  padding-left: .3rem;
-  font-size: .28rem;
+  padding-left: 5px;
   color: #CFAD89;
-text-decoration: none;
+  text-decoration: none;
 }
 
 .filter_tab .tab_right .vip_set_box:before {
   content: '';
   width: 1px;
-  height: 60%;
+  height: 100%;
   background: #E0E0E0;
   position: absolute;
   left: 0;
-  top: 20%;
+  top: 0;
 }
 
 .filter_tab .area_container {

+ 76 - 0
src/web/staticres/vipsubscribe/css/vipreport_dialog.css

@@ -0,0 +1,76 @@
+@charset "UTF-8";
+/* 解决编译过程中闪烁的问题 */
+[v-cloak] {
+  display: none !important;
+}
+
+.vip_report_tip {
+  width: 100%;
+  height: 100%;
+  display: none;
+  position: fixed;
+  left: 0px;
+  right: 0px;
+  bottom: 0px;
+  top: 0px;
+  z-index:2000;
+}
+
+.vip_report_tip .weui-dialog {
+  width: 5.92rem;
+  height: 7.4rem;
+  border-radius: 0.16rem;
+  overflow: visible !important;
+}
+
+.vip_report_tip .weui-dialog .my-dialog__hd {
+  position: relative;
+  display: flex;
+  width: 100%;
+  height: 100%;
+  flex-direction: column;
+  align-items: center;
+}
+
+.vip_report_tip .weui-dialog .my-dialog__hd .jy_title {
+  min-width: 1.28rem;
+  height: 0.48rem;
+  font-size: 0.32rem;
+  color: #5F5E64;
+  margin-top: -0.24rem;
+}
+
+.vip_report_tip .weui-dialog .my-dialog__hd .weekly {
+  min-width: 3.2rem;
+  height: 0.6rem;
+  font-size: 0.4rem;
+  font-weight: bold;
+  line-height: inherit;
+}
+
+.vip_report_tip .weui-dialog .my-dialog__hd .term {
+  width: 100%;
+  height: 0.4rem;
+  margin-top: 0.16rem;
+  font-size: 0.26rem;
+}
+
+.vip_report_tip .weui-dialog .my-dialog__hd .vip_report_todetail {
+  width: 4.96rem;
+  height: 0.88rem;
+  background-color: #2ABED1;
+  border-radius: 0.8rem;
+  color: #FFFFFF;
+  font-size: 0.36rem;
+  margin-top: 0.8rem;
+  line-height: 0.88rem;
+}
+
+.vip_report_tip .weui-dialog .my-dialog__hd .vip_report_tip_close {
+  position: absolute;
+  right: 1%;
+  top: -10.33%;
+  width: 0.56rem;
+  height: 0.56rem;
+  color: #FFFFFF;
+}

+ 3 - 0
src/web/staticres/vipsubscribe/image/vipreport/close.svg

@@ -0,0 +1,3 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M12 20C16.4183 20 20 16.4183 20 12C20 7.58172 16.4183 4 12 4C7.58172 4 4 7.58172 4 12C4 16.4183 7.58172 20 12 20ZM12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22ZM13.4143 12L16.2427 14.8284L14.8285 16.2426L12 13.4142L9.17161 16.2426L7.75739 14.8284L10.5858 12L7.75742 9.17158L9.17163 7.75736L12 10.5858L14.8285 7.75736L16.2427 9.17157L13.4143 12Z" fill="white"/>
+</svg>

BIN
src/web/staticres/vipsubscribe/image/vipreport/dialog-image.png


BIN
src/web/staticres/vipsubscribe/image/vipreport/report.png


+ 1 - 1
src/web/templates/pchelper/pushView.html

@@ -507,7 +507,7 @@
 				<a class="active" href="javascript:;" style="width:100px;">最新订阅信息</a>
 			</li>
 		</ul>
-		<div class="right-tabBtn">
+		<div class="right-tabBtn" style="visibility:hidden;">
 			<button class="active" id="right-list">列表</button>
 			<button id="right-table">表格</button>
 		</div>

+ 103 - 25
src/web/templates/weixin/historypush.html

@@ -24,7 +24,8 @@
 	<link rel="stylesheet" href="{{Msg "seo" "cdn"}}/vipsubscribe/iconfont/iconfont.css" />
 	<link rel="stylesheet" href="{{Msg "seo" "cdn"}}/vipsubscribe/css/base.css?v={{Msg "seo" "version"}}" />
 	<link rel="stylesheet" href="{{Msg "seo" "cdn"}}/vipsubscribe/css/public.css?v={{Msg "seo" "version"}}">
-	<link rel="stylesheet" href="{{Msg "seo" "cdn"}}/vipsubscribe/css/subscribe_list.css?v={{Msg "seo" "version"}}11211">
+	<link rel="stylesheet" href="{{Msg "seo" "cdn"}}/vipsubscribe/css/subscribe_list.css?v={{Msg "seo" "version"}}">
+	<link rel="stylesheet" href="{{Msg "seo" "cdn"}}/vipsubscribe/css/vipreport_dialog.css?v={{Msg "seo" "version"}}">
 	<script>
 		var zbadd = {{Msg "seo" "ZBADDRESS"}};
 		var firstPage = null;
@@ -245,7 +246,7 @@
 				$(".normal_set").show();
 				$(".tab_left .area").hide();
 				$(".vip_banner").show();
-				$(".subscribe").css("margin-top","2rem");
+				$(".subscribe").css("margin-top","105px");
 				if(isPassCount){
 					$(".open_remind").show();
 				}
@@ -293,6 +294,7 @@
 						}
 					}
 				}else{
+          $('.filter_tab').css("font-size","14px");
 					if(parseInt(isExpire)>1){
 						$("._renew_toast .isExpire").text(parseInt(isExpire));
 						$("._renew_toast").show();
@@ -303,7 +305,32 @@
 					}
 				}
 				$(".vip_set").show();
+				$(".vip_report").show();
 				$(".tab_left .area").show();
+				$.post("/subscribepay/report/tip",null,function(r){
+					if(r.unread>0){
+						$(".vip_report>span>a").show();
+					}
+					if(r.tip){
+						if(r.tip.type==2){
+							$(".vip_report_tip .weekly>span").text("周");	
+						}else{
+							$(".vip_report_tip .weekly>span").text("月");
+						}
+						$(".vip_report_tip .term").text(new Date(Number(r.tip.startdate+"000")).Format("yyyy年M月d日")+"-"+new Date(Number(r.tip.enddate+"000")).Format("yyyy年M月d日"));	
+						$('.vip_report_tip').fadeIn();
+						$('.vip_report_todetail').on('click',function(){
+							updateReportStatus(1,r.tip.startdate,r.tip.enddate,r.tip.pushcount);
+						});
+						$('.weui-dialog img.vip_report_tip_close').click(function(){
+							$('.vip_report_tip').fadeOut();
+							updateReportStatus(0);
+						});
+					}
+				});
+				$(".vip_report").click(function(){
+					window.location.href = "/vipreport/page/subreport.html?source=report";
+				});
 			}
 		}
 		//
@@ -706,7 +733,7 @@
 		.listcontent{
 			padding:0px 10px;
 			background: #fff;
-			margin-top: .20rem;
+			margin-top: 60px;
 		}
 		.adv-wxpush-center {
 		    width: 100%;
@@ -823,15 +850,45 @@
 			width: 100%;
 			z-index: 999;
 		}
-		.listcontent{
-			margin-top: 1rem;
-		}
 		.province_city p:last-child{
 			margin-bottom:1rem;
 		}
 		.province p:last-child{
 			margin-bottom:1rem;
 		}
+		.tab_right>div{
+			display: inline-block;
+		}
+		.vip_report{
+			color: #686868;
+      padding-right: .05rem;
+      vertical-align: top;
+      position: relative;
+      top: 2px;
+		}
+		.vip_report>span{
+			position: relative;
+			padding-right: 3px;
+		}
+		.vip_report>span>img{
+			width: 22px;
+      position: relative;
+      top: -1px;
+		}
+		.vip_report>span>a{
+      display: none;
+			position: absolute;
+      top: -4.5px;
+      right: 0px;
+      background-color: #FE737A;
+      width: 8px;
+      height: 8px;
+      border-radius: 100%;
+      z-index: 1;
+		}
+    .tab_right>.vip_set{
+      vertical-align: middle;
+    }
 	</style>
 </head>
 <body>
@@ -861,6 +918,9 @@
 				</div>
 			</div>
 			<div class="tab_right">
+				<div class="vip_report" style="display: none;">
+					<span><a></a><img src="/vipsubscribe/image/vipreport/report.png"></span><font>报告</font>
+				</div>
                 <div class="normal_set" style="display: none;" id="normal_set">
                   	<div class="normal_set_box">
                         <i class="icon iconfont">&#xe633;</i>
@@ -870,7 +930,7 @@
               	<div class="vip_set" style="display: none;">
               		<a onclick="tosetpage()" class="vip_set_box"  style="text-decoration: none;">
               			<span class="free7days_pic"></span>
-              			<span style="text-decoration: none;">VIP订阅设置</span>
+              			<span style="text-decoration: none;">VIP设置</span>
               		</a>
               	</div>
 	         </div>
@@ -952,6 +1012,19 @@
       	</div>
       </div>
   	</div>
+	<div class="vip_report_tip">
+		<div class="weui-mask weui-animate-fade-in"></div>
+		<div class="weui-dialog weui-animate-fade-in">
+			<div class="my-dialog__hd">
+				<img src="/vipsubscribe/image/vipreport/dialog-image.png" alt="">
+				<div class="jy_title">剑鱼标讯</div>
+				<h2 class="weekly">每<span></span>订阅报告来啦</h2>
+				<div class="term"></div>
+				<a href="javascript:void(0)" class="vip_report_todetail">点击查看</a>
+				<img src="/vipsubscribe/image/vipreport/close.svg" class="vip_report_tip_close">
+			</div>
+		</div>
+	</div>
   	<script src="{{Msg "seo" "cdn"}}/vipsubscribe/js/weui.min.js?v={{Msg "seo" "version"}}"></script>
   	<script src="{{Msg "seo" "cdn"}}/vipsubscribe/js/mapArea.js?v={{Msg "seo" "version"}}"></script>
   	<script type="text/javascript" charset="UTF-8">
@@ -973,7 +1046,7 @@
   				}
 				//所选地级市的数量
   				if(allCityNum>0){
-  					 $('#showArea .jymobile-tab-triangle').addClass('current').text(`地区 ${allCityNum}`);
+  					 $('#showArea .jymobile-tab-triangle').addClass('current').text("地区 "+allCityNum);
   				}
 				//sessionStorage.removeItem("selectCityName");
   			}
@@ -1066,7 +1139,7 @@
 				}
                 var cityCountDOM = $('.province .p_item').eq(i).children('.city-count')
                 if (checkedCityNum) {
-                	cityCountDOM.show().text(`(${checkedCityNum})`)
+                	cityCountDOM.show().text("("+checkedCityNum+")")
                 } else {
                 	cityCountDOM.show().text('')
                 	cityCountDOM.hide()
@@ -1144,10 +1217,10 @@
             		className: 'jymobile-datePicker',
             		onChange: function (result) {},
             		onConfirm: function (result) {
-            			let year = result[0].value;
-            			let month = result[1].value < 10 ? '0' + result[1].value : result[1].value;
-            			let day = result[2].value < 10 ? '0' + result[2].value:result[2].value;
-            			let time_result = year + '.' + month + '.' + day;
+            			var year = result[0].value;
+            			var month = result[1].value < 10 ? '0' + result[1].value : result[1].value;
+            			var day = result[2].value < 10 ? '0' + result[2].value:result[2].value;
+            			var time_result = year + '.' + month + '.' + day;
             			FTAGData(year + '-' + month + '-' + day)
             			$('.time_result').html(time_result)
             		}
@@ -1163,8 +1236,7 @@
                 var timeResult = timeResultBox.text()
                 if (timeResult !== '时间') {
                     // 给日期选择器添加footer
-                    var footerHTML = `<div class="weui-picker__ft">
-                    <div class="reset-time weui-picker__action" data-action="cancel">查看全部时间</div></div>`
+                    var footerHTML = '<div class="weui-picker__ft"><div class="reset-time weui-picker__action" data-action="cancel">查看全部时间</div></div>'
                     $('.jymobile-datePicker .weui-picker').append(footerHTML)
                     // 日期选择器样式添加--end---------------------
                     $('.jymobile-datePicker .weui-picker__ft').on('click', function(){
@@ -1215,19 +1287,19 @@
             // 地区选择确认按钮
             $('.enter_btn').click(function (){
             	$(".subscribe").toggleClass('overClass');
-            	let cityCount = $('.area_wrap .city input:checked').length-$('.area_wrap .city .cityAll input:checked').length;
+            	var cityCount = $('.area_wrap .city input:checked').length-$('.area_wrap .city .cityAll input:checked').length;
             	$('.area_container').slideUp();
             	$('.screen').hide()
                 selectCity = "" //重新选择 初始化地区 参数
 
             	if(!cityCount){
-            		$('#showArea .jymobile-tab-triangle').removeClass('current').text(`地区`);
+            		$('#showArea .jymobile-tab-triangle').removeClass('current').text("地区");
             		 ajaxFun(firstTime,selectCity);
             		return
             	}
 
                 // cityName对象
-                let selectCityName = []
+                var selectCityName = []
                 // 判断省份后面的数字是否隐藏来确定该省份下的城市有没有被选择
                 $('.area_wrap .province .p_item').each(function(i, dom){
                 	var f = $(dom).find('.city-count').is(':hidden')
@@ -1261,30 +1333,36 @@
                 sessionStorage.setItem(userId+"_selectCityName", JSON.stringify(selectCityName));
                 ajaxFun(firstTime,selectCity);
                 // 重写地区text
-                $('#showArea .jymobile-tab-triangle').addClass('current').text(`地区 ${cityCount}`);
+                $('#showArea .jymobile-tab-triangle').addClass('current').text("地区 "+cityCount);
                 
             })
             $('.reset_btn').click(function (){
-            	$('#showArea .jymobile-tab-triangle').text(`地区`);
+            	$('#showArea .jymobile-tab-triangle').text("地区");
             	$('.area_wrap .province .city-count').hide().text('')
             	$('.c_item input[type="checkbox"]').prop('checked', false)
             })
             // 关闭设置弹窗
-            $('#close_set').on('click',() =>{
+            $('#close_set').on('click',function(){
             	$('.set_keyword').hide()
             })
-            $('#close_renew').on('click',() =>{
+            $('#close_renew').on('click',function(){
             	$('.renew_toast').hide()
             })
-            $('#_close_renew').on('click',() =>{
+            $('#_close_renew').on('click',function(){
             	$('._renew_toast').hide()
             })
-            $('#nv_close_renew').on('click',() =>{
+            $('#nv_close_renew').on('click',function(){
 				localStorage.setItem("nv_vip_"+userId,"T");
             	$('.nv_renew_toast').hide()
             })
-            
         })
+		function updateReportStatus(type,start,end,pushcount){
+			$.post("/subscribepay/report/tipover",null,function(r){
+				if(type==1){
+					window.location.href = "/vipreport/page/reportdetail.html?start="+start+"&end="+end+"&pushcount="+pushcount;
+				}
+			});
+		}
     </script>
     <div id="advertscript" class="hidden adv-wxpush-center">
     	{{$s:=(Ad "jy-wxpush-middle" -1)}}