张金坤 8 năm trước cách đây
mục cha
commit
f7bbf6133c

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 0 - 0
src/jfw/modules/push/src/config.json


+ 47 - 30
src/jfw/modules/push/src/qfw/push/dopush/dopush.go

@@ -4,6 +4,7 @@ import (
 	"container/list"
 	"fmt"
 	"log"
+	"os"
 	"qfw/push"
 	"qfw/util"
 	"qfw/util/mail"
@@ -12,7 +13,6 @@ import (
 	"regexp"
 	"strconv"
 	"strings"
-	"sync"
 	"time"
 )
 
@@ -22,10 +22,7 @@ var re *regexp.Regexp
 var MAXLen = 200
 var TitleLen, ContentLen, GroupLen int
 var WxTitle, WxContent, WxGroup string
-var Mailpos = 0
-var MailposLock = &sync.Mutex{}
-var MailMap = []*mail.MailAuth{}
-var MailFrom = "剑鱼招标订阅"
+var GmailMap *mail.GmailAuth
 var Domain = ""
 var (
 	mail_html    = ""
@@ -33,18 +30,6 @@ var (
 	mail_title   = ""
 )
 
-//获取邮箱配置
-func GetSMail() (auth *mail.MailAuth) {
-	defer util.Catch()
-	MailposLock.Lock()
-	defer MailposLock.Unlock()
-	Mailpos %= len(MailMap)
-	auth = MailMap[Mailpos]
-	Mailpos++
-	time.Sleep(80 * time.Millisecond)
-	return
-}
-
 //初始化推送信息
 func Inits() {
 	//推送标题
@@ -68,11 +53,12 @@ func Inits() {
 	//初始化服务邮箱
 	arrMap := util.ObjArrToMapArr(push.PushConfig["mails"].([]interface{}))
 	for i := 0; i < len(arrMap); i++ {
-		MailMap = append(MailMap,
-			&mail.MailAuth{util.ObjToString(arrMap[i]["addr"]),
-				util.IntAll(arrMap[i]["port"]),
-				util.ObjToString(arrMap[i]["user"]),
-				util.ObjToString(arrMap[i]["pwd"])})
+		GmailMap = &mail.GmailAuth{
+			SmtpHost: util.ObjToString(arrMap[i]["addr"]),
+			SmtpPort: util.IntAll(arrMap[i]["port"]),
+			User:     util.ObjToString(arrMap[i]["user"]),
+			Pwd:      util.ObjToString(arrMap[i]["pwd"]),
+		}
 	}
 	Domain = push.PushConfig["bidViewDomain"].(string)
 }
@@ -109,6 +95,8 @@ func DealSend(k *push.MemberInterest, v *list.List, now time.Time, MaxPushSize i
 	publishTitle := map[string]bool{}
 	FilterData.Start(k.Openid)
 	defer FilterData.End()
+	//邮件附件
+	var fmdatas = []map[string]interface{}{}
 	for ks := v.Front(); ks != nil; ks = ks.Next() {
 		k2 := *(ks.Value.(*map[string]interface{}))
 		title := strings.Replace(k2["title"].(string), "\n", "", -1)
@@ -140,6 +128,21 @@ func DealSend(k *push.MemberInterest, v *list.List, now time.Time, MaxPushSize i
 						types = "其他"
 					}
 				}
+				classIndustry := "industry"
+				industry := util.ObjToString(k2["industry"])
+				if industry != "" {
+					industry = strings.TrimLeft(industry, ",")
+					industry = strings.TrimRight(industry, ",")
+					inds := strings.Split(industry, ",")
+					if len(inds) > 0 {
+						inds_ins := strings.Split(inds[0], "_")
+						if len(inds_ins) > 1 {
+							industry = inds_ins[len(inds_ins)-1]
+						} else {
+							industry = inds_ins[0]
+						}
+					}
+				}
 				dates := util.LongToDate(k2["publishtime"], false)
 				//标题替换
 				otitle := util.ObjToString(k2["otitle"])
@@ -161,7 +164,7 @@ func DealSend(k *push.MemberInterest, v *list.List, now time.Time, MaxPushSize i
 						break
 					}
 				}
-				mailContent += fmt.Sprintf(mail_content, i, url, otitle, classArea, area, classType, types, dates)
+				mailContent += fmt.Sprintf(mail_content, i, url, otitle, classArea, area, classType, types, classIndustry, industry, dates)
 			}
 			//str += "<div class='tslist'><span class='xh'>" + fmt.Sprintf("%d", i) + ".</span><a class='bt' target='_blank' sid='" + _sid + "' href='" + util.ObjToString(k2["href"]) + "'>" + title + "</a></div>"
 			str += "<div class='tslist'><span class='xh'>" + fmt.Sprintf("%d", i) + ".</span><a class='bt' target='_blank' eid='" + _sid + "' href='" + util.ObjToString(k2["href"]) + "'>" + title + "</a></div>"
@@ -174,6 +177,18 @@ func DealSend(k *push.MemberInterest, v *list.List, now time.Time, MaxPushSize i
 			if k2["highlight"] != nil {
 				o_pushinfo[strconv.Itoa(i)]["highlight"] = k2["highlight"]
 			}
+			//附件数据
+			fmdata := map[string]interface{}{
+				"publishtime": k2["publishtime"],
+				"subtype":     k2["subtype"],
+				"buyer":       k2["buyer"],
+				"projectname": k2["projectname"],
+				"budget":      k2["budget"],
+				"bidopentime": k2["bidopentime"],
+				"winner":      k2["winner"],
+				"bidamount":   k2["bidamount"],
+			}
+			fmdatas = append(fmdatas, fmdata)
 			if i >= MaxPushSize {
 				//限制最大信息条数
 				break
@@ -252,22 +267,24 @@ func DealSend(k *push.MemberInterest, v *list.List, now time.Time, MaxPushSize i
 		log.Println("-----", k.Openid)
 		wid = SendWeixin(k, str, now, Tip1+WXTitle+LastTip, o_pushinfo, ratemode, infoTypeName)
 	}
-
 	//3、发送邮件
 	if bmail {
 		html := fmt.Sprintf(mail_html, strings.Replace(strings.Join(k.Interest, ";"), "+", " ", -1), mailContent)
-		go SendEmail(k.Email, html, fmt.Sprintf(mail_title, infoTypeName))
+		subject := fmt.Sprintf(mail_title, infoTypeName)
+		go SendFmail(k.Email, subject, html, fmdatas)
 		if wid == "" { //保存信息
 			SaveSendInfo(k, now, html, o_pushinfo, ratemode)
 		}
 	}
 }
 
-//推送邮件
-func SendEmail(email, str, title string) {
-	auth := GetSMail()
-	if auth != nil {
-		mail.SendMail(auth, &mail.Message{title, MailFrom, []string{email}, str})
+//推送邮件(含附件)
+func SendFmail(email, subject, html string, fmdatas []map[string]interface{}) {
+	//生成附件
+	fname := GetBidInfoXlsx(fmdatas)
+	b := mail.GSendMail(email, "", "", subject, html, fname, GmailMap)
+	if b {
+		os.Remove(fname)
 	}
 }
 

+ 3 - 1
src/jfw/modules/push/src/qfw/push/dopush/dopushes.go

@@ -16,7 +16,8 @@ import (
 )
 
 const (
-	ShowField  = `"_id","title","publishtime","toptype","subtype","type","area","href","areaval","infoformat"`
+	ShowField = `"_id","title","publishtime","toptype","subtype","type","area","href","areaval","infoformat",` +
+		`"projectname","buyer","winner","agency","budget","bidamount","bidopentime","industry"`
 	FindField  = `"title"`
 	SortQuery  = `{"publishtime":"desc"}`
 	DB         = "bidding"
@@ -137,6 +138,7 @@ func PushInfoByEs(MaxPushSize int, Config *map[string]interface{}, i_ratemode in
 	} else {
 		q["o_jy.i_ratemode"] = i_ratemode
 	}
+	q["s_m_openid"] = "oHwE_wI94DGaSDks9ky5Yj8qqSx8"
 	query := session.DB("qfw").C("user").Find(&q).Select(&map[string]interface{}{
 		"_id":        1,
 		"o_jy":       1,

+ 115 - 0
src/jfw/modules/push/src/qfw/push/dopush/excel.go

@@ -0,0 +1,115 @@
+package dopush
+
+import (
+	"fmt"
+	"math/rand"
+	qu "qfw/util"
+	"time"
+
+	"github.com/xuri/excelize"
+)
+
+var fMailTitle = map[string]map[string]interface{}{
+	"A1": {"title": "发布时间", "width": 3},
+	"B1": {"title": "公告类型", "width": 3},
+	"C1": {"title": "招标单位", "width": 5},
+	"D1": {"title": "项目名称", "width": 5},
+	"E1": {"title": "预算(万元)", "width": 3},
+	"F1": {"title": "开标时间", "width": 4},
+	"G1": {"title": "中标单位", "width": 5},
+	"H1": {"title": "中标金额(万元)", "width": 3},
+}
+var kv = map[string]string{
+	"publishtime": "A",
+	"subtype":     "B",
+	"buyer":       "C",
+	"projectname": "D",
+	"budget":      "E",
+	"bidopentime": "F",
+	"winner":      "G",
+	"bidamount":   "H",
+}
+var font = `"font":{"color":"#FFFFFF"}`
+var fill = `"fill":{"type":"gradient","color":["#4F81BD","#4F81BD"],"shading":6}`
+var border = `"border":[{"type":"left","color":"000000","style":1},{"type":"top","color":"000000","style":1},{"type":"bottom","color":"000000","style":1},{"type":"right","color":"000000","style":1}]`
+var alignment = `"alignment":{"horizontal":"center","vertical":"center","wrap_text":true}`
+var alignmentleft = `"alignment":{"horizontal":"left","vertical":"center","wrap_text":true}`
+var alignmentright = `"alignment":{"horizontal":"right","vertical":"center","wrap_text":true}`
+var sheet = "Sheet1"
+var sheetName = "剑鱼推送"
+
+func GetBidInfoXlsx(data []map[string]interface{}) string {
+	xlsx := excelize.NewFile()
+	xlsx.NewSheet(2, "Sheet2")
+	var style, styleleft, styleright int
+	style, _ = xlsx.NewStyle(`{` + font + `,` + fill + `,` + alignment + `,` + border + `}`)
+	for k, v := range fMailTitle {
+		title := v["title"].(string)
+		width := float64(v["width"].(int) * 5)
+		xlsx.SetCellStr(sheet, k, title)
+		xlsx.SetColWidth(sheet, k[0:1], k[0:1], width)
+		xlsx.SetRowHeight(sheet, 0, 25)
+		xlsx.SetCellStyle(sheet, k, k, style)
+	}
+	//信息
+	style, _ = xlsx.NewStyle(`{` + alignment + `,` + border + `}`)
+	styleleft, _ = xlsx.NewStyle(`{` + alignmentleft + `,` + border + `}`)
+	styleright, _ = xlsx.NewStyle(`{` + alignmentright + `,` + border + `}`)
+	for k, v := range data {
+		pt := v["publishtime"]
+		publishtime := qu.FormatDateWithObj(&pt, qu.Date_Short_Layout)
+		key := kv["publishtime"] + fmt.Sprint(k+2)
+		xlsx.SetCellValue(sheet, key, publishtime)
+		xlsx.SetCellStyle(sheet, key, key, style)
+
+		key = kv["subtype"] + fmt.Sprint(k+2)
+		xlsx.SetCellValue(sheet, key, v["subtype"])
+		xlsx.SetCellStyle(sheet, key, key, style)
+
+		key = kv["buyer"] + fmt.Sprint(k+2)
+		xlsx.SetCellValue(sheet, key, v["buyer"])
+		xlsx.SetCellStyle(sheet, key, key, styleleft)
+
+		key = kv["projectname"] + fmt.Sprint(k+2)
+		xlsx.SetCellValue(sheet, key, v["projectname"])
+		xlsx.SetCellStyle(sheet, key, key, styleleft)
+
+		key = kv["budget"] + fmt.Sprint(k+2)
+		budget := qu.Float64All(v["budget"]) / float64(10000)
+		if budget != 0 {
+			xlsx.SetCellValue(sheet, key, budget)
+		} else {
+			xlsx.SetCellValue(sheet, key, "")
+		}
+		xlsx.SetCellStyle(sheet, key, key, styleright)
+
+		bpt := v["bidopentime"]
+		bidopentime := qu.FormatDateWithObj(&bpt, "2006-01-02 15:04")
+		key = kv["bidopentime"] + fmt.Sprint(k+2)
+		xlsx.SetCellValue(sheet, key, bidopentime)
+		xlsx.SetCellStyle(sheet, key, key, style)
+
+		key = kv["winner"] + fmt.Sprint(k+2)
+		xlsx.SetCellValue(sheet, key, v["winner"])
+		xlsx.SetCellStyle(sheet, key, key, styleleft)
+
+		key = kv["bidamount"] + fmt.Sprint(k+2)
+		bidamount := qu.Float64All(v["bidamount"]) / float64(10000)
+		if bidamount != 0 {
+			xlsx.SetCellValue(sheet, key, bidamount)
+		} else {
+			xlsx.SetCellValue(sheet, key, "")
+		}
+		xlsx.SetCellStyle(sheet, key, key, styleright)
+	}
+	xlsx.SetSheetName(sheet, sheetName)
+	xlsx.DeleteSheet("Sheet2")
+	fname := time.Now().Format("20060102150405")
+	fname = "./xlsx/" + fname + fmt.Sprint(rand.Intn(10000)) + ".xlsx"
+	err := xlsx.SaveAs(fname)
+	if err != nil {
+		return ""
+	} else {
+		return fname
+	}
+}

+ 16 - 0
src/jfw/modules/pushent/src/config.json

@@ -0,0 +1,16 @@
+{
+    "durationMinutes": "3",
+    "elasticPoolSize": 30,
+    "elasticsearch": "http://192.168.3.18:9800",
+    "lastid": "58579a5a012a9abbe627de52",
+    "mongodbName": "qfw",
+    "mongodbPoolSize": "20",
+    "mongodbServers": "192.168.3.18:27080",
+    "redisServers": "sso=192.168.3.14:1379,other=192.168.3.14:1379,push=192.168.3.14:3379", 
+    "rpcPort": "8759",
+    "viewDomain": "192.168.3.78",
+    "weixinRpcServer": "123.56.103.12:8202",
+    "wxcontent": "剑鱼推送",
+    "wxgroup": "关注企业",
+    "wxtitle": "您关注的企业《%s》有新的公告信息!"
+}

+ 11 - 0
src/jfw/modules/pushent/src/config/config.go

@@ -0,0 +1,11 @@
+package config
+
+import (
+	"qfw/util"
+)
+
+var Sysconfig map[string]interface{}
+
+func init() {
+	util.ReadConfig(&Sysconfig)
+}

+ 71 - 0
src/jfw/modules/pushent/src/filterdata/filterdata.go

@@ -0,0 +1,71 @@
+package filterdata
+
+import (
+	"encoding/json"
+	"log"
+	"qfw/util/redis"
+)
+
+var FilterData *filterDataEntity
+
+type filterDataEntity struct {
+	Array  []string
+	OpenId string
+}
+
+func init() {
+	FilterData = &filterDataEntity{
+		Array: []string{},
+	}
+}
+
+//获取数据
+func (fde *filterDataEntity) Start(openid string) {
+	if openid == "" {
+		return
+	}
+	fde.OpenId = openid
+	data := redis.Get("push", "push_ent_"+openid)
+	if data == nil {
+		return
+	}
+	b, err := json.Marshal(data)
+	if err != nil {
+		log.Println("从redis中取出的数据转成byte数组出错!")
+		return
+	}
+	var array []string
+	if json.Unmarshal(b, &array) != nil {
+		log.Println("byte数组转成string数组出错!")
+		return
+	}
+	fde.Array = array
+}
+
+//判断数据是否存在
+func (fde *filterDataEntity) IsExists(_id string) bool {
+	if _id == "" {
+		return false
+	}
+	for _, v := range fde.Array {
+		if _id == v {
+			return true
+		}
+	}
+	//log.Println(fde.Array)
+	fde.Array = append(fde.Array, _id)
+	return false
+}
+
+//添加数据
+func (fde *filterDataEntity) End(flag int) {
+	if fde.OpenId != "" && flag == 0 {
+		if len(fde.Array) > 0 {
+			redis.Put("push", "push_ent_"+fde.OpenId, fde.Array, -1)
+		} else {
+			redis.Del("push", "push_ent_"+fde.OpenId)
+		}
+	}
+	fde.Array = []string{}
+	fde.OpenId = ""
+}

+ 14 - 0
src/jfw/modules/pushent/src/followpush/config.json

@@ -0,0 +1,14 @@
+{
+    "durationMinutes": "1",
+    "lastid": "168418e062684db687cb0624",
+    "mongodbName": "qfw",
+    "mongodbPoolSize": "20",
+    "mongodbServers": "192.168.3.18:27080",
+    "redisServers": "sso=192.168.3.14:1379,other=192.168.3.14:1379,push=192.168.3.14:3379",
+    "rpcPort": "8759",
+    "viewDomain": "192.168.3.78",
+    "weixinRpcServer": "127.0.0.1:80",
+    "wxcontent": "剑鱼推送",
+    "wxgroup": "关注项目",
+    "wxtitle": "您关注的项目《%s》有新的公告信息!"
+}

+ 138 - 0
src/jfw/modules/pushent/src/followpush/datastruct.go

@@ -0,0 +1,138 @@
+package followpush
+
+import (
+	"qfw/util"
+	"tools"
+)
+
+//构建推送时需要排序的map
+type Arr []*map[string]interface{}
+
+func (a *Arr) Len() int {
+	return len(*a)
+}
+func (a *Arr) Less(i, j int) bool {
+	return util.Int64All((*(*a)[i])["publishtime"]) < util.Int64All((*(*a)[j])["publishtime"])
+}
+func (a *Arr) Swap(i, j int) {
+	tmp := (*a)[i]
+	(*a)[i] = (*a)[j]
+	(*a)[j] = tmp
+}
+
+type DFA struct {
+	Link map[string]interface{}
+}
+
+func (d *DFA) AddWord(keys ...string) {
+	if d.Link == nil {
+		d.Link = make(map[string]interface{})
+	}
+	for _, key := range keys {
+		nowMap := &d.Link
+		for i := 0; i < len(key); i++ {
+			kc := key[i : i+1]
+			if v, ok := (*nowMap)[kc]; ok {
+				nowMap, _ = v.(*map[string]interface{})
+			} else {
+				newMap := map[string]interface{}{}
+				newMap["YN"] = false
+				(*nowMap)[kc] = &newMap
+				nowMap = &newMap
+			}
+			if i == len(key)-1 {
+				(*nowMap)["YN"] = true
+				(*nowMap)["K"] = key
+			}
+		}
+	}
+}
+
+//适合一次查找
+func (d *DFA) CheckSensitiveWord(src string) string {
+	pos := 0
+	nowMap := &d.Link
+	res := ""
+	for i := 0; i < len(src); i++ {
+		word := src[i : i+1]
+		nowMap, _ = (*nowMap)[word].(*map[string]interface{})
+		if nowMap != nil { // 存在,则判断是否为最后一个
+			if pos == 0 {
+				pos = i
+			}
+			if (*nowMap)["YN"].(bool) { // 如果为最后一个匹配规则,结束循环,返回匹配标识数
+				res = util.ObjToString((*nowMap)["K"])
+				pos = 0
+				break
+			}
+		} else {
+			nowMap = &d.Link
+			if pos > 0 {
+				i = pos
+				pos = 0
+			}
+		}
+	}
+	return res
+}
+
+var titleSensitiveDFA DFA
+
+//2.用户关注标题敏感词构建
+func CreateTSM() {
+	titleSensitiveDFA = DFA{}
+	keys := []string{}
+	for k, _ := range Setting {
+		keys = append(keys, k)
+	}
+	titleSensitiveDFA.AddWord(keys...)
+}
+
+//1.用户关注普通map构建
+func UpdateUserSetting() bool {
+	//绝对相等才可以
+	//包括项目名称、项目编号
+	res := false
+	defer util.Catch()
+	//【项目编号|项目名称】*【openid】【title|项目名称】
+	////【项目编号|项目名称】[]*tmp
+	//pcode = &Setting{map[string]*map[string]string{}}
+	Setting = map[string]*[]*map[string]interface{}{}
+	sess := tools.MQFW.GetMgoConn()
+	defer tools.MQFW.DestoryMongoConn(sess)
+	cur := sess.DB(tools.MQFW.DbName).C(FOLLOW_COLLECTION).Find(&map[string]interface{}{
+		"s_openid": map[string]interface{}{
+			"$exists": true,
+		},
+		"i_ispush": map[string]interface{}{
+			"$ne": 0,
+		},
+	}).Select(map[string]interface{}{
+		"s_projectcode": 1,
+		"s_projectname": 1,
+		"s_title":       1,
+		"s_openid":      1,
+		"_id":           1,
+	}).Iter()
+	j := 0
+	for tmp := make(map[string]interface{}); cur.Next(tmp); j++ {
+		defer util.Catch()
+		mtmp := tmp
+		for _, v := range []string{"s_projectcode", "s_projectname"} {
+			pc := util.ObjToString(mtmp[v])
+			if len(pc) > 3 {
+				map1 := Setting[pc]
+				if map1 == nil {
+					map1 = &([]*map[string]interface{}{})
+					Setting[pc] = map1
+				}
+				*map1 = append(*map1, &mtmp)
+			}
+		}
+		tmp = make(map[string]interface{})
+	}
+	res = true
+	//构建敏感词
+	CreateTSM()
+	return res
+}

+ 44 - 0
src/jfw/modules/pushent/src/followpush/followpush.go

@@ -0,0 +1,44 @@
+package followpush
+
+import (
+	. "config"
+	"log"
+	"qfw/util"
+	"sync"
+)
+
+const (
+	FOLLOW_COLLECTION = "jylab_followent"
+	FOLLOW_PUSH_LOG   = "jylab_followent_pushlog"
+)
+
+//每次推前构建用户关注内存结构 项目名称和项目代码对应 用户组
+var Setting map[string]*[]*map[string]interface{}
+var WxTitle, WxContent, WxGroup, ViewDomain string
+var Lock = sync.Mutex{}
+
+//加密串
+var se util.SimpleEncrypt
+
+//推送不能大于200个字
+var LastLen int
+
+func init() {
+	se = util.SimpleEncrypt{Key: "topnet"}
+	WxTitle = util.ObjToString(Sysconfig["wxtitle"])
+	WxContent = util.ObjToString(Sysconfig["wxcontent"])
+	WxGroup = util.ObjToString(Sysconfig["wxgroup"])
+	ViewDomain = util.ObjToString(Sysconfig["viewDomain"])
+	LastLen = 200 - len([]rune(WxContent)) - len([]rune(WxGroup))
+}
+
+//开始查询最新的数据,推给用户
+var muser map[*map[string]interface{}]*[]*map[string]interface{}
+
+func Job() {
+	Lock.Lock()
+	defer Lock.Unlock()
+	lastid := util.ObjToString(Sysconfig["lastid"])
+	log.Println("start push followent info..", lastid)
+	pushByEs(lastid)
+}

+ 18 - 0
src/jfw/modules/pushent/src/followpush/followpush_test.go

@@ -0,0 +1,18 @@
+package followpush
+
+import (
+	"log"
+	"testing"
+	"time"
+)
+
+func Test_updateSetting(t *testing.T) {
+	UpdateUserSetting()
+	for k, v := range Setting {
+		for _, vv := range *v {
+			log.Println(k, (*vv)["s_openid"])
+		}
+	}
+	Job()
+	time.Sleep(100 * time.Second)
+}

+ 233 - 0
src/jfw/modules/pushent/src/followpush/push.go

@@ -0,0 +1,233 @@
+package followpush
+
+import (
+	. "config"
+	"filterdata"
+	"fmt"
+	"log"
+	"qfw/util"
+	"qfw/util/elastic"
+	qrpc "qfw/util/rpc"
+	"sort"
+	"strconv"
+	"strings"
+	"sync"
+	"time"
+	"tools"
+	"weixinrpc"
+
+	"gopkg.in/mgo.v2/bson"
+)
+
+var (
+	MaxId   = `{"query":{"filtered":{"filter":{"bool":{"must":{"range":{"id":{"gt":"%s"}}}}}}},"_source":["_id","comeintime"],"sort":{"id":"desc"},"from":0,"size":1}`
+	Query   = `{ "query": { "bool": { "must": [%s], "should": [%s], "minimum_should_match": 1 } }, "_source": [ "_id","title","publishtime","area","type","toptype","subtype","projectname","projectcode","href","infoformat" ], "sort": [ { "publishtime": "desc" } ], "from": 0, "size": 50 }`
+	IDRange = `{"range":{"id":{"gt":"%s","lte":"%s"}}}`
+	TERM    = `{"term":{"%s":"%s"}}`
+	DB      = "bidding"
+)
+
+//开始推送
+func pushByEs(_id string) bool {
+	defer util.Catch()
+	resId := elastic.Get(DB, DB, fmt.Sprintf(MaxId, _id))
+	lastid := ""
+	log.Println("push-lastid", _id, resId)
+	if resId != nil && *resId != nil && len(*resId) == 1 {
+		lastid = util.ObjToString((*resId)[0]["_id"])
+	} else {
+		log.Println("未查找到数据...", fmt.Sprintf(MaxId, _id))
+		return false
+	}
+	idrange := fmt.Sprintf(IDRange, _id, lastid)
+	sess := tools.MQFW.GetMgoConn()
+	defer tools.MQFW.DestoryMongoConn(sess)
+	cur := sess.DB(tools.MQFW.DbName).C(FOLLOW_COLLECTION).Find(&map[string]interface{}{
+		"s_openid": map[string]interface{}{
+			"$exists": true,
+		},
+		"i_ispush": map[string]interface{}{
+			"$ne": 0,
+		},
+	}).Select(map[string]interface{}{
+		"s_entname": 1,
+		"s_userid":  1,
+		"s_openid":  1,
+		"_id":       1,
+	}).Iter()
+	j := 0
+	for tmp := make(map[string]interface{}); cur.Next(tmp); j++ {
+		util.Try(func() {
+			entname := util.ObjToString(tmp["s_entname"])
+			openid := util.ObjToString(tmp["s_openid"])
+			go FindData(tmp["_id"], util.ObjToString(tmp["s_title"]), entname, openid, idrange, true, true)
+		}, func(e interface{}) {
+			log.Println(e)
+		})
+		tmp = make(map[string]interface{})
+	}
+	log.Println("push-over,user-count:", j)
+	Sysconfig["lastid"] = lastid
+	return true
+}
+
+var findpool = make(chan bool, 10)
+var Pushlock = sync.Mutex{}
+
+//不保存不推送-只保存不推送-保存推送
+func FindData(fid interface{}, title, sname, openid, idrange string, bsave, bpush bool) *Arr {
+	findpool <- true
+	defer func() {
+		<-findpool
+	}()
+	q1 := []string{}
+	if sname != "" {
+		q1 = append(q1, fmt.Sprintf(TERM, "winner", elastic.ReplaceYH(sname)))
+		//q1 = append(q1, fmt.Sprintf(TERM, "subtype", "中标"))
+	}
+	var pushArray = &Arr{}
+	if len(q1) > 0 {
+		res := elastic.Get(DB, DB, fmt.Sprintf(Query, idrange, strings.Join(q1, ",")))
+		if res != nil && *res != nil && len(*res) > 0 {
+			//顺序处理,后序会有性能瓶颈,filterdata
+			util.Try(func() {
+				if !bsave {
+					for _, info := range *res {
+						tmp := map[string]interface{}{}
+						sid := util.BsonIdToSId(info["_id"])
+						if title != sid { //title在此处传的是关注信息id
+							tmp["s_id"] = sid
+							tmp["s_eid"] = util.EncodeArticleId2ByCheck(sid)
+							tmp["s_title"] = info["title"]
+							tmp["l_publishtime"] = info["publishtime"]
+							tmp["s_province"] = info["area"]
+							tmp["s_type"] = util.ObjToString(info["type"])
+							tmp["s_toptype"] = util.ObjToString(info["toptype"])
+							tmp["s_subtype"] = util.ObjToString(info["subtype"])
+							tmp["s_entname"] = util.ObjToString(info["winner"])
+							tmp["s_url"] = util.ObjToString(info["href"])
+							*pushArray = append(*pushArray, &tmp)
+						}
+					}
+				} else {
+					Pushlock.Lock()
+					defer Pushlock.Unlock()
+					filterdata.FilterData.Start(openid)
+					defer filterdata.FilterData.End(0)
+					//1.组织信息、
+					//a_relationinfo s_id s_title s_projectname  s_projectcode  l_publishtime s_url
+					var ids []string
+					for _, info := range *res {
+						tmp := map[string]interface{}{}
+						sid := util.BsonIdToSId(info["_id"])
+						tmp["s_id"] = sid
+						tmp["s_eid"] = util.EncodeArticleId2ByCheck(sid)
+						tmp["s_title"] = info["title"]
+						tmp["l_publishtime"] = info["publishtime"]
+						tmp["s_province"] = info["area"]
+						tmp["s_type"] = util.ObjToString(info["type"])
+						tmp["s_toptype"] = util.ObjToString(info["toptype"])
+						tmp["s_subtype"] = util.ObjToString(info["subtype"])
+						tmp["s_entname"] = util.ObjToString(info["winner"])
+						tmp["s_url"] = util.ObjToString(info["href"])
+						if filterdata.FilterData.IsExists(sid) {
+							continue
+						}
+						ids = append(ids, sid)
+						*pushArray = append(*pushArray, &tmp)
+					}
+					go func() {
+						//2.推送、
+						if pushArray.Len() > 0 {
+							sort.Sort(pushArray)
+							//更新用户关注的a_relationinfo、保存到推送记录表、推送给用户
+							//log.Println(fid, ids)
+							if fid != nil && tools.MQFW.Update(FOLLOW_COLLECTION, &bson.M{
+								"_id": fid,
+							}, &bson.M{
+								"$set": bson.M{
+									"l_lastpushtime": (*((*pushArray)[0]))["l_publishtime"],
+									"a_lastpushids":  ids,
+								},
+								/*
+									"$pushAll": bson.M{
+										"a_relationinfo": pushArray,
+									},
+								*/
+							}, false, false) && bpush {
+								//进入推送逻辑
+								tit := sname
+								if tit == "" {
+									tit = title
+								}
+								if tit != "" {
+									//go func() {
+									followid := util.BsonIdToSId(fid)
+									infoid := tools.MQFW.Save(FOLLOW_PUSH_LOG, &bson.M{
+										"s_openid":       openid,
+										"a_relationinfo": pushArray,
+										"l_date":         time.Now().Unix(),
+										"s_title":        title,
+										"s_entname":      sname,
+										"s_followid":     followid,
+									})
+									if infoid != "" {
+										lastTime := util.Int64All((*(*pushArray)[0])["l_publishtime"])
+										pushtt := fmt.Sprintf(WxTitle, tit)
+										Tip1 := ""
+										minute := time.Now().Unix() - lastTime
+										if minute > -1 && minute < 61 {
+											Tip1 = fmt.Sprintf("%d秒前发布的:\n", minute)
+										} else {
+											minute = minute / 60
+											if minute < 121 {
+												if minute < 1 {
+													minute = 1
+												}
+												Tip1 = fmt.Sprintf("%d分钟前发布的:\n", minute)
+											}
+										}
+										LastTip := ""
+										pushnum := len(*pushArray)
+										if pushnum > 1 {
+											LastTip = fmt.Sprintf("...(共%d条)", pushnum)
+										}
+										LastLen = LastLen - len([]rune(pushtt)) - len([]rune(Tip1))
+										Remark := ""
+										bshow := false
+										for n := 1; n < pushnum+1; n++ {
+											Remark += fmt.Sprintf("%d %s\n", n, (*(*pushArray)[n-1])["s_title"])
+											if len([]rune(Remark)) > LastLen {
+												if n == pushnum {
+													bshow = true
+												}
+												break
+											}
+										}
+										if bshow {
+											LastTip = ""
+										}
+										go log.Println("push", openid, pushnum, tit)
+										weixinrpc.SendWinXin(&qrpc.NotifyMsg{
+											Openid:  openid,
+											Title:   fmt.Sprintf(WxTitle, tit),
+											Remark:  Tip1 + Remark + LastTip,
+											Detail:  WxContent,
+											Service: WxGroup,
+											Url:     ViewDomain + "/front/sess/" + se.EncodeString(openid+",uid,"+strconv.Itoa(int(time.Now().Unix()))+",wxpushfollowlist") + "__" + infoid + "__" + followid,
+										})
+									}
+									//}()
+								}
+								//推送结束
+							}
+						}
+					}()
+				}
+			}, func(e interface{}) {
+				log.Println("给用户推送关注信息时出错:", e)
+			})
+		}
+	}
+	return pushArray
+}

+ 46 - 0
src/jfw/modules/pushent/src/main.go

@@ -0,0 +1,46 @@
+package main
+
+import (
+	"config"
+	"followpush"
+	"log"
+	"net"
+	"net/http"
+	_ "net/http/pprof"
+	"net/rpc"
+	"qfw/util"
+	"qfw/util/elastic"
+	"qfw/util/redis"
+	"rpcpush"
+	"time"
+	"timetask"
+)
+
+func init() {
+	redis.InitRedisBySize(config.Sysconfig["redisServers"].(string), 200, 30, 300)
+	elastic.InitElasticSize(config.Sysconfig["elasticsearch"].(string), util.IntAllDef(config.Sysconfig["elasticPoolSize"], 30))
+}
+
+func main() {
+	time.Sleep(2 * time.Second)
+	log.Println(config.Sysconfig["rpcPort"], config.Sysconfig)
+	go runJob()
+	go timetask.ClearRedis()
+	crpc := new(rpcpush.FollowPushRpc)
+	rpc.Register(crpc)
+	rpc.HandleHTTP()
+	port, _ := config.Sysconfig["rpcPort"].(string)
+	l, _ := net.Listen("tcp", ":"+port)
+	go http.Serve(l, nil)
+	log.Println("启动关注推送系统", port)
+	b := make(chan bool)
+	<-b
+}
+
+func runJob() {
+	util.Try(func() {
+		followpush.Job()
+		util.WriteSysConfig(config.Sysconfig)
+	}, func(e interface{}) {})
+	time.AfterFunc(time.Duration(util.IntAll(config.Sysconfig["durationMinutes"]))*time.Minute, runJob)
+}

+ 27 - 0
src/jfw/modules/pushent/src/main_test.go

@@ -0,0 +1,27 @@
+package main
+
+import (
+	"log"
+	"strings"
+	"testing"
+
+	"gopkg.in/mgo.v2/bson"
+)
+
+func Test_main(t *testing.T) {
+	tmp := make(map[string]interface{})
+	tmp["ss"] = "ssss"
+	ss := tmp
+	m1 := map[string]*map[string]interface{}{}
+	m1["aa"] = &ss
+	tmp = make(map[string]interface{})
+	log.Println(m1["aa"])
+
+	log.Println(bson.ObjectIdHex("100000ee36b82b12a0000001").Hex())
+
+}
+
+func Test_1(t *testing.T) {
+	log.Println(strings.Contains("aassdf", "0"))
+
+}

+ 33 - 0
src/jfw/modules/pushent/src/rpcpush/findData.go

@@ -0,0 +1,33 @@
+package rpcpush
+
+import (
+	"filterdata"
+	"followpush"
+	"log"
+
+	"gopkg.in/mgo.v2/bson"
+)
+
+func RpcFindFollow(entname, followid, thisid, openid string, flag int) *followpush.Arr {
+	bsave := false
+	var ff interface{}
+	if len(followid) > 5 {
+		bsave = true
+		ff = bson.ObjectIdHex(followid)
+	}
+	if thisid != "" && bsave {
+		log.Println(thisid, "--add follow")
+		go func() {
+			followpush.Pushlock.Lock()
+			defer followpush.Pushlock.Unlock()
+			filterdata.FilterData.Start(openid)
+			defer filterdata.FilterData.End(0)
+			filterdata.FilterData.IsExists(thisid)
+		}()
+	}
+	res := followpush.FindData(ff, thisid, entname, openid, "", bsave, false)
+	if flag == 1 {
+		return res
+	}
+	return nil
+}

+ 21 - 0
src/jfw/modules/pushent/src/rpcpush/rpcpush.go

@@ -0,0 +1,21 @@
+package rpcpush
+
+import (
+	"encoding/json"
+	"qfw/util"
+	qrpc "qfw/util/rpc"
+)
+
+type FollowPushRpc struct {
+}
+
+//RPC调用结果预览
+func (p *FollowPushRpc) FollowPushEnt(data *qrpc.FollowPushEnt, Reply *[]byte) error {
+	util.Try(func() {
+		res := RpcFindFollow(data.Entname, data.FollowId, data.InfoId, data.OpenId, data.Flag)
+		if res != nil {
+			*Reply, _ = json.Marshal([]*map[string]interface{}(*res))
+		}
+	}, func(e interface{}) {})
+	return nil
+}

+ 23 - 0
src/jfw/modules/pushent/src/timetask/clearredis.go

@@ -0,0 +1,23 @@
+package timetask
+
+import (
+	"log"
+	"qfw/util/redis"
+	"time"
+)
+
+//每天凌晨清redis
+func ClearRedis() {
+	for {
+		time.Sleep(30 * time.Second)
+		now := time.Now()
+		//每天凌晨
+		next := time.Date(now.Year(), now.Month(), now.Day()+1, 0, 0, 0, 0, now.Location())
+		timer := time.NewTimer(next.Sub(now)) //自动删除
+		select {
+		case <-timer.C:
+			log.Println("每天凌晨清redis数据。")
+			redis.DelByCodePattern("push", "push_*")
+		}
+	}
+}

+ 18 - 0
src/jfw/modules/pushent/src/tools/mongo.go

@@ -0,0 +1,18 @@
+package tools
+
+import (
+	. "config"
+	"qfw/util"
+	"qfw/util/mongodb"
+)
+
+var MQFW mongodb.MongodbSim
+
+func init() {
+	MQFW = mongodb.MongodbSim{
+		MongodbAddr: Sysconfig["mongodbServers"].(string),
+		Size:        util.IntAll(Sysconfig["mongodbPoolSize"]),
+		DbName:      Sysconfig["mongodbName"].(string),
+	}
+	MQFW.InitPool()
+}

+ 1 - 0
src/jfw/modules/pushent/src/tools/tools.go

@@ -0,0 +1 @@
+package tools

+ 76 - 0
src/jfw/modules/pushent/src/weixinrpc/weixinrpc.go

@@ -0,0 +1,76 @@
+package weixinrpc
+
+import (
+	"config"
+	"log"
+	"net/rpc"
+	"qfw/util"
+	qrpc "qfw/util/rpc"
+	"strings"
+	"time"
+	"tools"
+)
+
+var wxpool chan bool = make(chan bool, 30)
+
+//微信远程调用,实现模板发送消息
+func SendWinXin(p *qrpc.NotifyMsg) {
+	wxpool <- true
+	defer func() {
+		<-wxpool
+	}()
+	util.Try(func() {
+		client, err := rpc.DialHTTP("tcp", config.Sysconfig["weixinRpcServer"].(string))
+		defer client.Close()
+		if err != nil {
+			log.Println(err.Error())
+			return
+		}
+		var repl qrpc.RpcResult
+		err = client.Call("WeiXinRpc.SendPushMsg", p, &repl)
+		if err != nil {
+			log.Println(err.Error())
+		}
+		res := string(repl)
+		if strings.Contains(res, "[46004]") || strings.Contains(res, "[65302]") || strings.Contains(res, "[43004]") || strings.Contains(res, "[40003]") {
+			updateIsPush(p.Openid, 0)
+		}
+	}, func(e interface{}) {})
+	time.Sleep(10 * time.Millisecond)
+}
+
+//微信远程调用,实现模板发送消息
+func FollowPush(p *qrpc.NotifyMsg) {
+	wxpool <- true
+	defer func() {
+		<-wxpool
+	}()
+	util.Try(func() {
+		client, err := rpc.DialHTTP("tcp", config.Sysconfig["weixinRpcServer"].(string))
+		defer client.Close()
+		if err != nil {
+			log.Println(err.Error())
+			return
+		}
+		var repl qrpc.RpcResult
+		err = client.Call("WeiXinRpc.SendPushMsg", p, &repl)
+		if err != nil {
+			log.Println(err.Error())
+		}
+	}, func(e interface{}) {})
+	time.Sleep(10 * time.Millisecond)
+}
+
+//修改是否推送的状态
+func updateIsPush(openid string, status int) {
+	tools.MQFW.Update("user", map[string]interface{}{"s_m_openid": openid}, map[string]interface{}{
+		"$set": map[string]interface{}{
+			"i_ispush": status,
+		},
+	}, false, false)
+	tools.MQFW.Update("jylab_followent", map[string]interface{}{"s_openid": openid}, map[string]interface{}{
+		"$set": map[string]interface{}{
+			"i_ispush": status,
+		},
+	}, false, true)
+}

+ 5 - 3
src/jfw/modules/pushproject/src/followpush/push.go

@@ -155,9 +155,11 @@ func FindData(fid interface{}, title, sname, scode, openid, idrange string, bsav
 									"l_lastpushtime": (*((*pushArray)[0]))["l_publishtime"],
 									"a_lastpushids":  ids,
 								},
-								"$pushAll": bson.M{
-									"a_relationinfo": pushArray,
-								},
+								/*
+									"$pushAll": bson.M{
+										"a_relationinfo": pushArray,
+									},
+								*/
 							}, false, false) && bpush {
 								//进入推送逻辑
 								tit := sname

Một số tệp đã không được hiển thị bởi vì quá nhiều tập tin thay đổi trong này khác