Bläddra i källkod

Merge branch 'master' of https://jygit.jydev.jianyu360.cn/moapp/jypkg

wangshan 11 månader sedan
förälder
incheckning
9b1f82f668

+ 16 - 3
common/src/qfw/util/dataexport/common.go

@@ -3,10 +3,17 @@ package dataexport
 import (
 	qutil "app.yhyue.com/moapp/jybase/common"
 	"app.yhyue.com/moapp/jybase/mysql"
+	"app.yhyue.com/moapp/jybase/redis"
 	"fmt"
 	"strings"
 )
 
+const (
+	RedisPoly               = "poly"     // 查白名单用户用的redis
+	WhitelistRedisKey       = "white_%s" // 白名单用户用的redis key
+	ResCount          int64 = -2
+)
+
 // GetLastExportPhoneAndMail 数据导出联想上次导出手机号和邮箱查询
 func GetLastExportPhoneAndMail(mysqlSess *mysql.Mysql, userId, entUserId string) (phone, email string) {
 	var searchSql []string
@@ -145,7 +152,13 @@ func KeyWordToDatas(item, key string, keyWord []string) []string {
 	return keyWord
 }
 
-// 获取关键词匹配字段
-func getKeywordFields() {
-
+// IsOnTheWhitelist 是否在白名单
+func IsOnTheWhitelist(userId, mgoUserId string) bool {
+	// 	mongoid 在白名单中没有查到 再去查职位id有没有在白名单里面
+	flag, err := redis.Exists(RedisPoly, fmt.Sprintf(WhitelistRedisKey, mgoUserId))
+	if err == nil && flag {
+		return flag
+	}
+	flag, err = redis.Exists(RedisPoly, fmt.Sprintf(WhitelistRedisKey, userId))
+	return flag
 }

+ 353 - 302
common/src/qfw/util/dataexport/dataexport.go

@@ -5,7 +5,6 @@ import (
 	"encoding/json"
 	"errors"
 	"fmt"
-	"github.com/gogf/gf/v2/util/gconv"
 	"log"
 	"math"
 	"regexp"
@@ -15,24 +14,33 @@ import (
 	"sync"
 	"time"
 
-	qutil "app.yhyue.com/moapp/jybase/common"
 	. "app.yhyue.com/moapp/jybase/date"
 	. "app.yhyue.com/moapp/jybase/encrypt"
+
+	"github.com/gogf/gf/v2/util/gconv"
+
+	qutil "app.yhyue.com/moapp/jybase/common"
 	elastic "app.yhyue.com/moapp/jybase/es"
 	mg "app.yhyue.com/moapp/jybase/mongodb"
 	"app.yhyue.com/moapp/jypkg/common/src/qfw/util/jy"
 )
 
 const (
-	SearchModeAccurate        = 0 // 搜索模式:0:精准搜索;
-	SearchModeFuzzy           = 1 // 搜索模式:1:模糊搜索
-	WordsModeAnd              = 0 // 搜索关键词模式;默认0:包含所有
-	WordsModeOr               = 1 // 搜索关键词模式;1:包含任意
-	SearchGroupAll            = 0 // 搜索分组:默认0:全部;
-	SearchGroupBidding        = 1 // 搜索分组:1:招标采购公告;2:超前项目
-	SearchGroupLeadingProject = 2 // 搜索分组:1:招标采购公告;2:超前项目
-	TopTypesBidding           = "招标预告,招标公告,招标结果,招标信用信息"
-	TopTypesLeadingProject    = "拟建项目,采购意向"
+	SearchModeAccurate             = 0 // 搜索模式:0:精准搜索;
+	SearchModeFuzzy                = 1 // 搜索模式:1:模糊搜索
+	WordsModeAnd                   = 0 // 搜索关键词模式;默认0:包含所有
+	WordsModeOr                    = 1 // 搜索关键词模式;1:包含任意
+	SearchGroupAll                 = 0 // 搜索分组:默认0:全部;
+	SearchGroupBidding             = 1 // 搜索分组:1:招标采购公告;2:超前项目
+	SearchGroupLeadingProject      = 2 // 搜索分组:1:招标采购公告;2:超前项目
+	SearchGroupAnnouncementProject = 3 // 搜索分组:1:招标采购公告;2:超前项目 移动3:公告 4 预告 5结果
+	SearchGroupPreviewsProject     = 4 // 搜索分组:1:招标采购公告;2:超前项目移动3:公告 4 预告 5结果
+	SearchGroupResultsProject      = 5 // 搜索分组:1:招标采购公告;2:超前项目移动3:公告 4 预告 5结果
+	TopTypesBidding                = "招标预告,招标公告,招标结果,招标信用信息"
+	TopTypesLeadingProject         = "拟建项目,采购意向"
+	TopTypesAnnouncementProject    = "招标公告"
+	TopTypesPreviewsProject        = "招标预告"
+	TopTypesResultsProject         = "招标结果"
 )
 
 /*筛选条件--关键词*/
@@ -52,6 +60,7 @@ type SieveCondition struct {
 	Industry         []string  `json:"industry"`         //行业
 	Keyword          []KeyWord `json:"keywords"`         //关键词
 	Buyer            []string  `json:"buyer"`            //招标单位(采购单位)
+	Agency           []string  `json:"agency"`           //招标代理机构(采购单位)
 	Buyerclass       []string  `json:"buyerclass"`       //采购单位类型
 	HasBuyerTel      string    `json:"hasBuyertel"`      //是否有采购单位电话
 	Winner           []string  `json:"winner"`           //中标单位
@@ -71,7 +80,9 @@ type SieveCondition struct {
 	SearchGroup      int       `json:"searchGroup"`      // 搜索分组:默认0:全部;1:招标采购公告;2:超前项目
 	SearchMode       int       `json:"searchMode"`       // 搜索模式:0:精准搜索;1:模糊搜索
 	WordsMode        int       `json:"wordsMode"`        // 搜索关键词模式;默认0:包含所有,1:包含任意
-	District         []string  `json:"district"`
+	District         []string  `json:"district"`         //
+	UserId           string    `json:"s_userid"`         //用户id 或 职位id
+	MgoUserId        string    `json:"mgoUserId"`        //mgoUserId
 }
 
 const (
@@ -110,6 +121,23 @@ func DetailANDTitle(findfields string) bool {
 	return strings.Contains(findfields, "detail") && strings.Contains(findfields, "title")
 }
 
+var getMatchPhraseSql = func(field string, val ...string) (sql string) {
+	if len(val) == 0 {
+		return
+	}
+	var arr []string
+	for _, s := range val {
+		if s == "" {
+			continue
+		}
+		arr = append(arr, fmt.Sprintf(`{"match_phrase": {"%s": "%s"}}`, field, s))
+	}
+	if len(arr) == 0 {
+		return ""
+	}
+	return fmt.Sprintf(`{"bool": {"should": [%s],"minimum_should_match": 1}}`, strings.Join(arr, ","))
+}
+
 // 获取数据导出查询语句
 func getDataExportSql(scd *SieveCondition) string {
 	if len(scd.SelectIds) > 0 {
@@ -211,10 +239,24 @@ func getDataExportSql(scd *SieveCondition) string {
 	timequery += `}}}`
 	musts = append(musts, timequery)
 	if scd.Subtype == "" {
-		if scd.SearchGroup == SearchGroupBidding { // 搜索分组处理  招标采购公告 超前项目
+		switch scd.SearchGroup {
+		case SearchGroupBidding:
 			scd.Subtype = TopTypesBidding
-		} else if scd.SearchGroup == SearchGroupLeadingProject {
+		case SearchGroupLeadingProject:
 			scd.Subtype = TopTypesLeadingProject
+		case SearchGroupAnnouncementProject:
+			scd.Subtype = TopTypesAnnouncementProject
+		case SearchGroupPreviewsProject:
+			scd.Subtype = TopTypesPreviewsProject
+		case SearchGroupResultsProject:
+			scd.Subtype = TopTypesResultsProject
+
+		}
+		if scd.SearchGroup == SearchGroupBidding { // 搜索分组处理  招标采购公告 超前项目
+
+		} else if scd.SearchGroup == SearchGroupLeadingProject {
+
+		} else {
 		}
 	}
 	if scd.Subtype != "" {
@@ -241,14 +283,25 @@ func getDataExportSql(scd *SieveCondition) string {
 	if len(scd.Industry) > 0 {
 		musts = append(musts, fmt.Sprintf(query_bool_must, "s_subscopeclass", `"`+strings.Join(scd.Industry, `","`)+`"`))
 	}
-	if len(scd.Buyer) > 0 {
-		musts = append(musts, fmt.Sprintf(query_bool_must, "buyer", `"`+strings.Join(scd.Buyer, `","`)+`"`))
-	}
 	if len(scd.Buyerclass) > 0 {
 		musts = append(musts, fmt.Sprintf(query_bool_must, "buyerclass", `"`+strings.Join(scd.Buyerclass, `","`)+`"`))
 	}
+	//P492招标采购搜索匹配采购单位等优化 新增buyer、agency、winner模糊搜索,数据导出同步改为模糊
+	//query_bool_should := `{"bool":{"should":[%s],"minimum_should_match": 1}}`
+	if len(scd.Buyer) > 0 {
+		if sql := getMatchPhraseSql("buyer.mbuyer", scd.Buyer...); sql != "" {
+			musts = append(musts, sql)
+		}
+	}
+	if len(scd.Agency) > 0 {
+		if sql := getMatchPhraseSql("agency.magency", scd.Agency...); sql != "" {
+			musts = append(musts, sql)
+		}
+	}
 	if len(scd.Winner) > 0 {
-		musts = append(musts, fmt.Sprintf(query_bool_must, "s_winner", `"`+strings.Join(scd.Winner, `","`)+`"`))
+		if sql := getMatchPhraseSql("s_winner.mwinner", scd.Winner...); sql != "" {
+			musts = append(musts, sql)
+		}
 	}
 	_minPrice := ""
 	_maxPrice := ""
@@ -495,6 +548,7 @@ func GetSqlObjFromId(mongo mg.MongodbSim, _id string) *SieveCondition {
 		SelectType:       qutil.ObjToString((*query)["selectType"]),
 		PublishTime:      qutil.ObjToString((*query)["publishtime"]),
 		Buyer:            getStringArrFromDbResult((*query)["buyer"]),
+		Agency:           getStringArrFromDbResult((*query)["agency"]),
 		Buyerclass:       getStringArrFromDbResult((*query)["buyerclass"]),
 		HasBuyerTel:      qutil.ObjToString((*query)["hasBuyertel"]),
 		Winner:           getStringArrFromDbResult((*query)["winner"]),
@@ -505,11 +559,13 @@ func GetSqlObjFromId(mongo mg.MongodbSim, _id string) *SieveCondition {
 		PushKeyWords:     getStringArrFromDbResult((*query)["pushKeyWords"]),
 		FileExists:       qutil.ObjToString((*query)["fileExists"]),
 		SearchTypeSwitch: searchTypeSwitch,
-		BidField:         qutil.ObjToString((*query)["bid_field"]), // 领域化数据
-		SearchGroup:      qutil.IntAll((*query)["searchGroup"]),    //搜索分组:默认0:全部;1:招标采购公告;2:超前项目
-		SearchMode:       qutil.IntAll((*query)["searchMode"]),     // 搜索模式:0:精准搜索;1:模糊搜索
-		WordsMode:        qutil.IntAll((*query)["wordsMode"]),      // 搜索关键词模式;默认0:包含所有,1:包含任意
-		District:         gconv.Strings((*query)["district"]),
+		BidField:         qutil.ObjToString((*query)["bid_field"]),    // 领域化数据
+		SearchGroup:      qutil.IntAll((*query)["searchGroup"]),       //搜索分组:默认0:全部;1:招标采购公告;2:超前项目
+		SearchMode:       qutil.IntAll((*query)["searchMode"]),        // 搜索模式:0:精准搜索;1:模糊搜索
+		WordsMode:        qutil.IntAll((*query)["wordsMode"]),         // 搜索关键词模式;默认0:包含所有,1:包含任意
+		District:         gconv.Strings((*query)["district"]),         //
+		UserId:           qutil.InterfaceToStr((*query)["s_userid"]),  //
+		MgoUserId:        qutil.InterfaceToStr((*query)["mgoUserId"]), //
 	}
 }
 
@@ -535,7 +591,7 @@ func GetDataExportSearchCountBySieveCondition(scd *SieveCondition, elasticAddres
 	}
 	// 依据用户选择的搜索模式和搜索范围进行匹配,即不限制只能匹配标题,且不限制最多展示100条、针对输入的单个关键词分词后需要都包含
 	//超级搜索一致的检索(防止数据导出和超级搜索数据量不一致)
-	if scd.Comeinfrom == "supersearchPage" && (len(scd.Keyword) != 0 || len(scd.Industry) != 0) && scd.SearchMode == SearchModeFuzzy {
+	if scd.Comeinfrom == "supersearchPage" && (len(scd.Keyword) != 0 || len(scd.Industry) != 0 || IsOnTheWhitelist(scd.UserId, scd.MgoUserId)) && scd.SearchMode == SearchModeFuzzy {
 		if len(scd.Keyword) != 0 {
 			// 关键词分词
 			searchTextSize := 0
@@ -628,23 +684,30 @@ func GetDataExportSelectReallyCountFromEs(ids []string) int64 {
 	wait := &sync.WaitGroup{}
 	var total int64
 	var lock sync.Mutex
-	for _, v := range SplitArray(ids, 200) {
-		pool <- true
-		wait.Add(1)
-		go func(arr []string) {
-			defer func() {
-				wait.Done()
-				<-pool
-			}()
-			query := fmt.Sprintf(`{"query":{"bool":{"must":[{"terms":{"id":["%s"]}}]}}}`, strings.Join(arr, "\",\""))
-			tCount := elastic.Count(INDEX, TYPE, query)
-			if tCount > 0 {
-				lock.Lock()
-				total += tCount
-				lock.Unlock()
-			}
-			return
-		}(v)
+	var idArr []string
+	for i, id := range ids {
+		idArr = append(idArr, id)
+		if len(idArr) == 200 || i+1 == len(ids) {
+			pool <- true
+			wait.Add(1)
+			go func(arr []string) {
+				defer func() {
+					wait.Done()
+					<-pool
+				}()
+				log.Println("GetDataExportSelectReallyCountFromEs===", arr[0])
+				query := fmt.Sprintf(`{"query":{"bool":{"must":[{"terms":{"id":["%s"]}}]}}}`, strings.Join(arr, "\",\""))
+				tCount := elastic.Count(INDEX, TYPE, query)
+				if tCount > 0 {
+					lock.Lock()
+					total += tCount
+					lock.Unlock()
+				}
+				return
+			}(idArr)
+			idArr = []string{}
+		}
+
 	}
 	wait.Wait()
 	log.Printf("GetDataExportSelectReallyCount 选择数据共%d条记录,实际查询%d条\n", len(ids), total)
@@ -665,47 +728,53 @@ func GetDataExportSelectReallyCountFromMongo(bid mg.MongodbSim, biddingName stri
 	)
 	pool := make(chan bool, 10)
 	wait := &sync.WaitGroup{}
-
-	for _, i2 := range SplitArray(ids, 200) {
-		pool <- true
-		wait.Add(1)
-		go func(arr []string) {
-			defer func() {
-				wait.Done()
-				<-pool
-			}()
-			lenNum := int64(len(arr))
-			var (
-				queryIds   []interface{}
-				num1, num2 int64
-				err        error
-			)
-			for _, idStr := range arr {
-				queryIds = append(queryIds, mg.StringTOBsonId(idStr))
-			}
-			num1, err = sess.DB(biddingName).C("bidding").Find(map[string]interface{}{"_id": map[string]interface{}{
-				"$in": queryIds,
-			}}).Count()
-			if err == nil {
-				if num1 == lenNum {
-					lock.Lock()
-					count += num1
-					lock.Unlock()
-					return
+	var idArr []string
+	for i, id := range ids {
+		idArr = append(idArr, id)
+		if len(idArr) == 200 || i+1 == len(ids) {
+			pool <- true
+			wait.Add(1)
+			go func(arr []string) {
+				defer func() {
+					wait.Done()
+					<-pool
+				}()
+				log.Println("GetDataExportSelectReallyCountFromMongo===", arr[0])
+				lenNum := int64(len(arr))
+				var (
+					queryIds   []interface{}
+					num1, num2 int64
+					err        error
+				)
+				for _, idStr := range arr {
+					queryIds = append(queryIds, mg.StringTOBsonId(idStr))
 				}
-				num2, err = sess.DB(biddingName).C("bidding_back").Find(map[string]interface{}{"_id": map[string]interface{}{
+				num1, err = sess.DB(biddingName).C("bidding").Find(map[string]interface{}{"_id": map[string]interface{}{
 					"$in": queryIds,
 				}}).Count()
 				if err == nil {
-					lock.Lock()
-					count += qutil.If(num2+num1 >= lenNum, lenNum, num2+num1).(int64)
-					lock.Unlock()
+					if num1 == lenNum {
+						lock.Lock()
+						count += num1
+						lock.Unlock()
+						return
+					}
+					num2, err = sess.DB(biddingName).C("bidding_back").Find(map[string]interface{}{"_id": map[string]interface{}{
+						"$in": queryIds,
+					}}).Count()
+					if err == nil {
+						lock.Lock()
+						count += qutil.If(num2+num1 >= lenNum, lenNum, num2+num1).(int64)
+						lock.Unlock()
+					}
 				}
-			}
-		}(i2)
+			}(idArr)
+			idArr = []string{}
+		}
+
 	}
 	wait.Wait()
-	return qutil.If(count > 0, count, -2).(int64)
+	return qutil.If(count > 0, count, ResCount).(int64)
 }
 
 func GetDataExportSelectResultFromEs(bidding mg.MongodbSim, biddingName string, scd *SieveCondition, dataType string, checkCount int) (*[]map[string]interface{}, error) {
@@ -716,19 +785,15 @@ func GetDataExportSelectResultFromEs(bidding mg.MongodbSim, biddingName string,
 	if checkCount == -1 && len(scd.SelectIds) > 500 {
 		scd.SelectIds = scd.SelectIds[:500]
 	}
-	pool := make(chan bool, 10)
-	wait := &sync.WaitGroup{}
-	var lock sync.Mutex
+
 	returnLsit := make([]map[string]interface{}, 0, len(scd.SelectIds))
-	for _, v := range SplitArray(scd.SelectIds, 200) {
-		pool <- true
-		wait.Add(1)
-		go func(arr []string) error {
-			defer func() {
-				wait.Done()
-				<-pool
-			}()
-			query := fmt.Sprintf(`{"query":{"bool":{"must":[{"terms":{"id":["%s"]}}]}},"_source": [%s],"size":%d}`, strings.Join(arr, "\",\""), bidField, len(arr))
+	var idArr []string
+	for i, id := range scd.SelectIds {
+		idArr = append(idArr, id)
+		if len(idArr) == 200 || i+1 == len(scd.SelectIds) {
+
+			log.Println(scd.Id, "GetDataExportSelectResultFromEs===", idArr[0])
+			query := fmt.Sprintf(`{"query":{"bool":{"must":[{"terms":{"id":["%s"]}}]}},"_source": [%s],"size":%d}`, strings.Join(idArr, "\",\""), bidField, len(idArr))
 			log.Println("GetDataExportSelectResultFromEs 数据流量包 es count 信息查询:", query)
 			data := *elastic.Get(INDEX, TYPE, query)
 			if data != nil && len(data) > 0 {
@@ -738,16 +803,13 @@ func GetDataExportSelectResultFromEs(bidding mg.MongodbSim, biddingName string,
 					if detail != "" {
 						bv["detail"] = contentfilterReg.ReplaceAllString(detail, "")
 					}
-					lock.Lock()
 					returnLsit = append(returnLsit, bv)
-					lock.Unlock()
 				}
 			}
-			return nil
-		}(v)
+			idArr = []string{}
+		}
 	}
-	wait.Wait()
-	if len(returnLsit) == checkCount || checkCount == -1 {
+	if len(returnLsit) == checkCount || checkCount == -1 || checkCount == -2 {
 		return &returnLsit, nil
 	} else {
 		return nil, fmt.Errorf("GetDataExportSelectResultFromEs 选择数据导出异常 数据量期望%d条,实际查询%d条", checkCount, len(returnLsit))
@@ -768,20 +830,18 @@ func GetDataExportSelectResultFromMongoDb(bidding mg.MongodbSim, biddingName str
 	if checkCount == -1 && len(scd.SelectIds) > 500 {
 		scd.SelectIds = scd.SelectIds[:500]
 	}
-	pool := make(chan bool, 10)
-	wait := &sync.WaitGroup{}
-	var lock sync.Mutex
 	returnLsit := make([]map[string]interface{}, 0, len(scd.SelectIds))
-	for _, v := range SplitArray(scd.SelectIds, 200) {
-		pool <- true
-		wait.Add(1)
-		go func(arr []string) error {
-			defer func() {
-				wait.Done()
-				<-pool
-			}()
-			var queryIds []interface{}
-			for _, idStr := range arr {
+	var idArr []string
+	for i, id := range scd.SelectIds {
+		idArr = append(idArr, id)
+		if len(idArr) == 200 || i+1 == len(scd.SelectIds) {
+
+			log.Println(scd.Id, "GetDataExportSelectResultFromMongoDb===", idArr[0])
+			var (
+				queryIds []interface{}
+				count    int
+			)
+			for _, idStr := range idArr {
 				queryIds = append(queryIds, mg.StringTOBsonId(idStr))
 			}
 			iter := sess.DB(biddingName).C("bidding").Select(selectMap).Find(map[string]interface{}{"_id": map[string]interface{}{
@@ -793,66 +853,35 @@ func GetDataExportSelectResultFromMongoDb(bidding mg.MongodbSim, biddingName str
 				if detail != "" {
 					m["detail"] = contentfilterReg.ReplaceAllString(detail, "")
 				}
-				lock.Lock()
+				count++
 				returnLsit = append(returnLsit, m)
-				lock.Unlock()
 				m = make(map[string]interface{})
 			}
-			iter_back := sess.DB(biddingName).C("bidding_back").Select(selectMap).Find(map[string]interface{}{"_id": map[string]interface{}{
-				"$in": queryIds,
-			}}).Iter()
-			for m := make(map[string]interface{}); iter_back.Next(&m); {
-				m["_id"] = mg.BsonIdToSId(m["_id"])
-				detail, _ := m["detail"].(string)
-				if detail != "" {
-					m["detail"] = contentfilterReg.ReplaceAllString(detail, "")
+			if count != len(idArr) {
+				iter_back := sess.DB(biddingName).C("bidding_back").Select(selectMap).Find(map[string]interface{}{"_id": map[string]interface{}{
+					"$in": queryIds,
+				}}).Iter()
+				for m := make(map[string]interface{}); iter_back.Next(&m); {
+					m["_id"] = mg.BsonIdToSId(m["_id"])
+					detail, _ := m["detail"].(string)
+					if detail != "" {
+						m["detail"] = contentfilterReg.ReplaceAllString(detail, "")
+					}
+					returnLsit = append(returnLsit, m)
+					m = make(map[string]interface{})
 				}
-				lock.Lock()
-				returnLsit = append(returnLsit, m)
-				lock.Unlock()
-				m = make(map[string]interface{})
 			}
-			return nil
-		}(v)
+
+			idArr = []string{}
+		}
 	}
-	wait.Wait()
-	if len(returnLsit) == checkCount || checkCount == -1 {
+	if len(returnLsit) == checkCount || checkCount == -1 || checkCount == -2 {
 		return &returnLsit, nil
 	} else {
 		return nil, fmt.Errorf("GetDataExportSelectResultFromMongoDb 选择数据导出异常 数据量期望%d条,实际查询%d条", checkCount, len(returnLsit))
 	}
 }
 
-// SplitArray 分割数组
-func SplitArray(arr []string, num int64) [][]string {
-	max := int64(len(arr))
-	//判断数组大小是否小于等于指定分割大小的值,是则把原数组放入二维数组返回
-	if max <= num {
-		return [][]string{arr}
-	}
-	//获取应该数组分割为多少份
-	var quantity int64
-	if max%num == 0 {
-		quantity = max / num
-	} else {
-		quantity = (max / num) + 1
-	}
-	//声明分割好的二维数组
-	var segments = make([][]string, 0)
-	//声明分割数组的截止下标
-	var start, end, i int64
-	for i = 1; i <= quantity; i++ {
-		end = i * num
-		if i != quantity {
-			segments = append(segments, arr[start:end])
-		} else {
-			segments = append(segments, arr[start:])
-		}
-		start = i * num
-	}
-	return segments
-}
-
 func GetDataExportIds(elasticAddress string, scd *SieveCondition, checkCount int) ([]string, error) {
 	defer qutil.Catch()
 	if scd == nil {
@@ -869,7 +898,7 @@ func GetDataExportIds(elasticAddress string, scd *SieveCondition, checkCount int
 	}
 	//超级搜索一致的检索(防止数据导出和超级搜索数据量不一致)
 	// 依据用户选择的搜索模式和搜索范围进行匹配,即不限制只能匹配标题,且不限制最多展示100条、针对输入的单个关键词分词后需要都包含
-	if scd.Comeinfrom == "supersearchPage" && (len(scd.Keyword) != 0 || len(scd.Industry) != 0) && len(scd.SelectIds) == 0 && scd.SearchMode == SearchModeFuzzy {
+	if scd.Comeinfrom == "supersearchPage" && (len(scd.Keyword) != 0 || len(scd.Industry) != 0 || IsOnTheWhitelist(scd.UserId, scd.MgoUserId)) && len(scd.SelectIds) == 0 && scd.SearchMode == SearchModeFuzzy {
 		if len(scd.Keyword) != 0 {
 			searchTextSize := 0
 			// 关键词分词
@@ -939,7 +968,7 @@ func GetDataExportSearchResult(bid mg.MongodbSim, bidMgoDBName, elasticAddress s
 		res = doSearchByBatch(qstr, dataType, checkCount, fmt.Sprintf("%s-%s", "GetDataExportSearchResult", scd.Id))
 	}
 	//超级搜索一致的检索(防止数据导出和超级搜索数据量不一致)
-	if scd.Comeinfrom == "supersearchPage" && (len(scd.Keyword) != 0 || len(scd.Industry) != 0) && len(scd.SelectIds) == 0 && scd.SearchMode == SearchModeFuzzy {
+	if scd.Comeinfrom == "supersearchPage" && (len(scd.Keyword) != 0 || len(scd.Industry) != 0 || IsOnTheWhitelist(scd.UserId, scd.MgoUserId)) && len(scd.SelectIds) == 0 && scd.SearchMode == SearchModeFuzzy {
 		if len(scd.Keyword) != 0 {
 			searchTextSize := 0
 			// 关键词分词
@@ -1045,176 +1074,198 @@ func FormatExportData(entmg mg.MongodbSim, data *[]map[string]interface{}, webdo
 	if len(encry) > 0 {
 		isEncry = true
 	}
+	sort.Slice(*data, func(i, j int) bool {
+		time1 := qutil.Int64All((*data)[i]["publishtime"])
+		time2 := qutil.Int64All((*data)[j]["publishtime"])
+		return time1 > time2
+	})
 	var entCacheMap = map[string]map[string]interface{}{}
+	pool := make(chan bool, 5)
+	wait := &sync.WaitGroup{}
+	lock := &sync.Mutex{}
 	for index := 0; index < len(*data); index++ {
-		v := (*data)[index]
-		//有中标企业 且 高级字段查询
-		if dataType == "2" {
-			//查询企业公示 法人 公司电话 公司邮箱地址
-			entidlist, ok := v["entidlist"].([]interface{})
-			if ok && len(entidlist) > 0 {
-				var winnerMaps []map[string]interface{}
-				for _, entIdObj := range entidlist {
-					entId := qutil.ObjToString(entIdObj)
-					if entId == "" {
-						continue
-					}
-					if entCacheMap[entId] != nil {
-						winnerMaps = append(winnerMaps, entCacheMap[entId])
-					} else if entDetail := elastic.Get("qyxy", "qyxy", fmt.Sprintf(`{"query":{"bool":{"must":[{"term":{"id":"%s"}}]}},"size":1,"_source":["company_name","company_email","company_phone","legal_person"]}`, entId)); entDetail != nil && len(*entDetail) > 0 {
-						thisEntMap := map[string]interface{}{}
-						legal_person := ""
-						if (*entDetail)[0]["legal_person"] != nil {
-							legal_person = (*entDetail)[0]["legal_person"].(string)
-							if isEncry {
-								var xx = "*"
-								switch len([]rune(legal_person)) {
-								case 3:
-									xx = "**"
-								case 4:
-									xx = "***"
+		pool <- true
+		wait.Add(1)
+		go func(v map[string]interface{}) {
+			defer qutil.Catch()
+			defer func() {
+				<-pool
+				wait.Done()
+			}()
+			//有中标企业 且 高级字段查询
+			if dataType == "2" {
+				//查询企业公示 法人 公司电话 公司邮箱地址
+				entidlist, ok := v["entidlist"].([]interface{})
+				if ok && len(entidlist) > 0 {
+					var winnerMaps []map[string]interface{}
+					for _, entIdObj := range entidlist {
+						entId := qutil.ObjToString(entIdObj)
+						if entId == "" {
+							continue
+						}
+						lock.Lock()
+						ecm := entCacheMap[entId]
+						lock.Unlock()
+						if ecm != nil {
+							winnerMaps = append(winnerMaps, ecm)
+						} else if entDetail := elastic.Get("qyxy", "qyxy", fmt.Sprintf(`{"query":{"bool":{"must":[{"term":{"id":"%s"}}]}},"size":1,"_source":["company_name","company_email","company_phone","legal_person"]}`, entId)); entDetail != nil && len(*entDetail) > 0 {
+							thisEntMap := map[string]interface{}{}
+							legal_person := ""
+							if (*entDetail)[0]["legal_person"] != nil {
+								legal_person = (*entDetail)[0]["legal_person"].(string)
+								if isEncry {
+									var xx = "*"
+									switch len([]rune(legal_person)) {
+									case 3:
+										xx = "**"
+									case 4:
+										xx = "***"
+									}
+									legal_person = string([]rune(legal_person)[:1]) + xx
 								}
-								legal_person = string([]rune(legal_person)[:1]) + xx
 							}
-						}
-						company_phone := ""
-						if (*entDetail)[0]["company_phone"] != nil {
-							company_phone = (*entDetail)[0]["company_phone"].(string)
-							if isEncry {
-								if len([]rune(company_phone)) > 7 {
-									company_phone = company_phone[:7] + "****"
-								} else {
-									company_phone = "****"
+							company_phone := ""
+							if (*entDetail)[0]["company_phone"] != nil {
+								company_phone = (*entDetail)[0]["company_phone"].(string)
+								if isEncry {
+									if len([]rune(company_phone)) > 7 {
+										company_phone = company_phone[:7] + "****"
+									} else {
+										company_phone = "****"
+									}
 								}
 							}
-						}
-						company_email := ""
-						if (*entDetail)[0]["company_email"] != nil && (*entDetail)[0]["company_email"] != "无" {
-							company_email = (*entDetail)[0]["company_email"].(string)
-							if isEncry {
-								if len(strings.Split(company_email, "@")) > 1 {
-									company_email = "******" + "@" + strings.Split(company_email, "@")[1]
+							company_email := ""
+							if (*entDetail)[0]["company_email"] != nil && (*entDetail)[0]["company_email"] != "无" {
+								company_email = (*entDetail)[0]["company_email"].(string)
+								if isEncry {
+									if len(strings.Split(company_email, "@")) > 1 {
+										company_email = "******" + "@" + strings.Split(company_email, "@")[1]
+									}
 								}
 							}
+							company_name := ""
+							if (*entDetail)[0]["company_name"] != nil {
+								company_name = (*entDetail)[0]["company_name"].(string)
+							}
+							thisEntMap["legal_person"] = legal_person
+							thisEntMap["company_phone"] = company_phone
+							thisEntMap["company_email"] = company_email
+							thisEntMap["company_name"] = company_name
+							lock.Lock()
+							entCacheMap[entId] = thisEntMap
+							lock.Unlock()
+							winnerMaps = append(winnerMaps, thisEntMap)
 						}
-						company_name := ""
-						if (*entDetail)[0]["company_name"] != nil {
-							company_name = (*entDetail)[0]["company_name"].(string)
-						}
-						thisEntMap["legal_person"] = legal_person
-						thisEntMap["company_phone"] = company_phone
-						thisEntMap["company_email"] = company_email
-						thisEntMap["company_name"] = company_name
-						entCacheMap[entId] = thisEntMap
-						winnerMaps = append(winnerMaps, thisEntMap)
+					}
+					if len(winnerMaps) > 0 {
+						v["winnerMaps"] = winnerMaps
 					}
 				}
-				if len(winnerMaps) > 0 {
-					v["winnerMaps"] = winnerMaps
-				}
+				delete(v, "entidlist")
 			}
-			delete(v, "entidlist")
-		}
-		//====================字段补漏=========================
-		if v["toptype"] == "结果" && dataType == "2" && !(v["agency"] != nil && v["budget"] != nil && v["buyerperson"] != nil && v["buyertel"] != nil) {
-			r := elastic.Get("projectset", "projectset", fmt.Sprintf(`{"query":{"term":{"list.infoid":"%s"}},"_source": ["list"]}`, v["_id"]))
-			if r != nil && len(*r) > 0 {
-				MsgList := (*r)[0]["list"]
-				if MsgList != nil {
-					list := qutil.ObjArrToMapArr(MsgList.([]interface{}))
-					for _, vv := range list {
-						if vv["subtype"] == "招标" {
-							if v["agency"] == nil && vv["agency"] != nil {
-								v["agency"] = vv["agency"]
-							}
-							if v["budget"] == nil && vv["budget"] != nil {
-								v["budget"] = vv["budget"]
-							}
-							if v["buyerperson"] == nil && vv["buyerperson"] != nil {
-								v["buyerperson"] = vv["buyerperson"]
-							}
-							if v["buyertel"] == nil && vv["buyertel"] != nil {
-								v["buyertel"] = vv["buyertel"]
+			//====================字段补漏=========================
+			if v["toptype"] == "结果" && dataType == "2" && !(v["agency"] != nil && v["budget"] != nil && v["buyerperson"] != nil && v["buyertel"] != nil) {
+				r := elastic.Get("projectset", "projectset", fmt.Sprintf(`{"query":{"term":{"list.infoid":"%s"}},"_source": ["list"]}`, v["_id"]))
+				if r != nil && len(*r) > 0 {
+					MsgList := (*r)[0]["list"]
+					if MsgList != nil {
+						list := qutil.ObjArrToMapArr(MsgList.([]interface{}))
+						for _, vv := range list {
+							if vv["subtype"] == "招标" {
+								if v["agency"] == nil && vv["agency"] != nil {
+									v["agency"] = vv["agency"]
+								}
+								if v["budget"] == nil && vv["budget"] != nil {
+									v["budget"] = vv["budget"]
+								}
+								if v["buyerperson"] == nil && vv["buyerperson"] != nil {
+									v["buyerperson"] = vv["buyerperson"]
+								}
+								if v["buyertel"] == nil && vv["buyertel"] != nil {
+									v["buyertel"] = vv["buyertel"]
+								}
+								break
 							}
-							break
 						}
 					}
 				}
 			}
-		}
-		if v["area"] == "A" {
-			v["area"] = "全国"
-		}
-		if v["bidamount"] != nil {
-			v["bidamount"] = formatFloat(qutil.Float64All(v["bidamount"]))
-		}
-		if v["budget"] != nil {
-			v["budget"] = formatFloat(qutil.Float64All(v["budget"]))
-		}
-		if v["publishtime"] != nil {
-			date := v["publishtime"]
-			v["publishtime"] = FormatDateWithObj(&date, Date_Short_Layout)
-		}
-		if v["bidopentime"] != nil {
-			date := v["bidopentime"]
-			v["bidopentime"] = FormatDateWithObj(&date, Date_Short_Layout)
-		}
-		if qutil.IntAll(v["signendtime"]) != 0 {
-			date := v["signendtime"]
-			v["signendtime"] = FormatDateWithObj(&date, Date_Short_Layout)
-		}
-		if v["bidendtime"] != nil {
-			date := v["bidendtime"]
-			v["bidendtime"] = FormatDateWithObj(&date, Date_Short_Layout)
-		}
-		if v["signaturedate"] != nil {
-			date := v["signaturedate"]
-			v["signaturedate"] = FormatDateWithObj(&date, Date_Short_Layout)
-		}
-		if v["_id"] != nil {
-			encodeId := CommonEncodeArticle("content", v["_id"].(string))
-			v["url"] = webdomain + "/article/content/" + encodeId + ".html"
-			v["url_jump"] = webdomain + "/front/reloadTo/article/content/" + encodeId + ".html"
-		}
-		if v["currency"] == "" || v["currency"] == nil {
-			v["currency"] = "人民币"
-		}
+			if v["area"] == "A" {
+				v["area"] = "全国"
+			}
+			if v["bidamount"] != nil {
+				v["bidamount"] = formatFloat(qutil.Float64All(v["bidamount"]))
+			}
+			if v["budget"] != nil {
+				v["budget"] = formatFloat(qutil.Float64All(v["budget"]))
+			}
+			if v["publishtime"] != nil {
+				date := v["publishtime"]
+				v["publishtime"] = FormatDateWithObj(&date, Date_Short_Layout)
+			}
+			if v["bidopentime"] != nil {
+				date := v["bidopentime"]
+				v["bidopentime"] = FormatDateWithObj(&date, Date_Short_Layout)
+			}
+			if qutil.IntAll(v["signendtime"]) != 0 {
+				date := v["signendtime"]
+				v["signendtime"] = FormatDateWithObj(&date, Date_Short_Layout)
+			}
+			if v["bidendtime"] != nil {
+				date := v["bidendtime"]
+				v["bidendtime"] = FormatDateWithObj(&date, Date_Short_Layout)
+			}
+			if v["signaturedate"] != nil {
+				date := v["signaturedate"]
+				v["signaturedate"] = FormatDateWithObj(&date, Date_Short_Layout)
+			}
+			if v["_id"] != nil {
+				encodeId := CommonEncodeArticle("content", v["_id"].(string))
+				v["url"] = webdomain + "/article/content/" + encodeId + ".html"
+				v["url_jump"] = webdomain + "/front/reloadTo/article/content/" + encodeId + ".html"
+			}
+			if v["currency"] == "" || v["currency"] == nil {
+				v["currency"] = "人民币"
+			}
 
-		if isEncry {
-			if v["projectscope"] != "" && v["projectscope"] != nil {
-				str := ClearHtml.ReplaceAllString(v["projectscope"].(string), "")
-				str = ClearOther.ReplaceAllString(str, "")
-				str = strings.Replace(str, " ", "", -1)
-				if len([]rune(str)) > 100 {
-					str = qutil.SubString(str, 0, 100) + "..."
+			if isEncry {
+				if v["projectscope"] != "" && v["projectscope"] != nil {
+					str := ClearHtml.ReplaceAllString(v["projectscope"].(string), "")
+					str = ClearOther.ReplaceAllString(str, "")
+					str = strings.Replace(str, " ", "", -1)
+					if len([]rune(str)) > 100 {
+						str = qutil.SubString(str, 0, 100) + "..."
+					}
+					v["projectscope"] = str
 				}
-				v["projectscope"] = str
-			}
-			if v["detail"] != "" && v["detail"] != nil {
-				str := ClearHtml.ReplaceAllString(v["detail"].(string), "")
-				str = ClearOther.ReplaceAllString(str, "")
-				str = strings.Replace(str, " ", "", -1)
-				if len([]rune(str)) > 100 {
-					str = qutil.SubString(str, 0, 100) + "..."
+				if v["detail"] != "" && v["detail"] != nil {
+					str := ClearHtml.ReplaceAllString(v["detail"].(string), "")
+					str = ClearOther.ReplaceAllString(str, "")
+					str = strings.Replace(str, " ", "", -1)
+					if len([]rune(str)) > 100 {
+						str = qutil.SubString(str, 0, 100) + "..."
+					}
+					v["detail"] = str
 				}
-				v["detail"] = str
-			}
-			if v["title"] != "" && v["title"] != nil {
-				str := ClearHtml.ReplaceAllString(v["title"].(string), "")
-				str = ClearOther.ReplaceAllString(str, "")
-				str = strings.Replace(str, " ", "", -1)
-				if len([]rune(str)) > 100 {
-					str = qutil.SubString(str, 0, 100) + "..."
+				if v["title"] != "" && v["title"] != nil {
+					str := ClearHtml.ReplaceAllString(v["title"].(string), "")
+					str = ClearOther.ReplaceAllString(str, "")
+					str = strings.Replace(str, " ", "", -1)
+					if len([]rune(str)) > 100 {
+						str = qutil.SubString(str, 0, 100) + "..."
+					}
+					v["title"] = str
 				}
-				v["title"] = str
-			}
 
-		}
+			}
 
-		if v["subtype"] == nil && v["toptype"] != nil {
-			v["subtype"] = v["toptype"]
-		}
+			if v["subtype"] == nil && v["toptype"] != nil {
+				v["subtype"] = v["toptype"]
+			}
+		}((*data)[index])
 	}
+	wait.Wait()
 	return data
 }
 

+ 6 - 0
common/src/qfw/util/dataexport/entdataexport.go

@@ -7,6 +7,7 @@ import (
 	"log"
 	"net/http"
 	"os"
+	"sort"
 	"strconv"
 	"strings"
 	"sync"
@@ -148,6 +149,11 @@ func FormatExportDatas(Mgo_Ent mongodb.MongodbSim, data *[]map[string]interface{
 		entexportPool      = make(chan bool, 20)
 		entexportWaitGroup = &sync.WaitGroup{}
 	)
+	sort.Slice(*data, func(i, j int) bool {
+		time1 := util.Int64All((*data)[i]["publishtime"])
+		time2 := util.Int64All((*data)[j]["publishtime"])
+		return time1 > time2
+	})
 	log.Println("补充信息开始")
 	for _, v := range *data {
 		entexportWaitGroup.Add(1)

+ 216 - 44
common/src/qfw/util/jy/ad.go

@@ -1,12 +1,52 @@
 package jy
 
 import (
+	qutil "app.yhyue.com/moapp/jybase/common"
+	"app.yhyue.com/moapp/jybase/mongodb"
+	"app.yhyue.com/moapp/jybase/mysql"
+	"app.yhyue.com/moapp/jybase/redis"
 	"encoding/json"
+	"fmt"
 	"log"
 	"strings"
 	"time"
 )
 
+const (
+	UserAttributeGuest         = "g"   // 用户身份  g-未登录
+	UserAttributeFree          = "f"   // 用户身份  f-免费
+	UserAttributeMember        = "m"   // 用户身份 m-大会员
+	UserAttributeVip           = "v"   // 用户身份 v-超级订阅
+	UserAttributeEntniche      = "e"   // 用户身份 e-商机管理
+	UserAttributeLimitM        = "lm"  // 用户身份 大会员(非超级订阅的大会员)
+	UserAttributeLimitMV       = "lmv" // 用户身份 大会员且超级订阅
+	UserAttributeLimitV        = "lv"  // 用户身份 超级订阅(非大会员的超级订阅)
+	UserAttributeNotMV         = "nmv" // 用户身份 非超级订阅非大会员的用户(可能是商机管理用户、免费用户)
+	UserAttributeDocsMember    = "dm"  //用户身份 文库会员
+	UB                         = true  //
+	OrderAttributeVipBuy       = "vb"  // 订单分类 vip购买
+	OrderAttributeVipRenew     = "vr"  // 订单分类 vip续费
+	OrderAttributeVipUpgrade   = "vu"  // 订单分类 vip升级
+	OrderAttributeBigMemberBuy = "bb"  // 订单分类 大会员购买
+	OrderAttributeNoHave       = "oan" //未查到对应订单信息
+)
+
+// 获取当天剩余时间
+var (
+	timeOut int64 = 24 * 60 * 60
+)
+
+type AdFunc struct {
+	AdCodes   []string            //广告位code
+	UserInfo  *BigVipBaseMsg      //用户信息
+	Mgo       *mongodb.MongodbSim //mongo
+	MySql     *mysql.Mysql        //tidb 订单表
+	Host      string              //域名
+	Ads       *[]byte             //
+	OrderCode string              //订单code
+	IsLogin   bool                //是否登录
+}
+
 // AdInfo 广告信息
 type AdInfo struct {
 	S_link   string `json:"s_link"`   //广告位跳转链接
@@ -15,69 +55,119 @@ type AdInfo struct {
 	S_picalt string `json:"s_picalt"` //图片ALT
 	S_id     string `json:"s_id"`     //广告标识id
 	O_extend struct {
-		Linktype  string `json:"linktype"`  //是否外部链接
-		Height    string `json:"height"`    //高度
-		Width     string `json:"width"`     //宽度
-		StartTime string `json:"startTime"` //开始时间
-		EndTime   string `json:"endTime"`   //结束时间
-		IosHref   string `json:"iosHref"`   //根据客户端不同 是否访问不同地址
-		Theme     string `json:"theme"`     // 主题样式
-		Title     string `json:"title"`     //标题
-		Power     string `json:"power"`     // 权限判断
-		Tab       string `json:"tab"`       // tab切换
+		Linktype       string `json:"linktype"`       //是否外部链接
+		Height         string `json:"height"`         //高度
+		Width          string `json:"width"`          //宽度
+		StartTime      string `json:"startTime"`      //开始时间
+		EndTime        string `json:"endTime"`        //结束时间
+		IosHref        string `json:"iosHref"`        //根据客户端不同 是否访问不同地址
+		Theme          string `json:"theme"`          //主题样式
+		Title          string `json:"title"`          //标题
+		Power          string `json:"power"`          //权限判断
+		Tab            string `json:"tab"`            //tab切换
+		UserAttribute  string `json:"userAttribute"`  //用户身份  g-未登录 f-免费 m-大会员 v-超级订阅 e-商机管理 多个时使用英文逗号分割
+		OrderAttribute string `json:"orderAttribute"` //订单类型 vb:vip购买;vr:vip续费;vu:vip升级;mb:大会员购买;
 	} `json:"o_extend"` //拓展属性
 	S_script string `json:"s_script"` //脚本
 }
 
-// Handle 广告位信息处理
-func Handle(data []interface{}, host string) []AdInfo {
-	var res = []AdInfo{}
-	if len(data) > 0 {
-		AdInfo_Arr := []AdInfo{}
-		bytes, err := json.Marshal(data)
-		if err != nil {
-			return res
+// 获取广告位
+func (a *AdFunc) GetAdInfos() (adInfoMap map[string][]AdInfo) {
+	if len(a.AdCodes) > 0 {
+		adInfoMap = map[string][]AdInfo{}
+		for _, sCode := range a.AdCodes {
+			obj, err := redis.GetBytes("other", "ad_"+sCode)
+			if err == nil && obj != nil && len(*obj) > 0 {
+				a.Ads = obj
+				adInfoMap[sCode] = a.Handle()
+			} else {
+				res, ok := a.Mgo.FindOneByField("ad", `{"s_code":"`+sCode+`"}`, `{"a_son":1}`)
+				if ok && res != nil && (*res)["a_son"] != nil {
+					if (*res)["a_son"] != nil {
+						b, err := json.Marshal((*res)["a_son"])
+						if err == nil && len(b) > 0 {
+							a.Ads = &b
+							if err = redis.PutBytes("other", "ad_"+sCode, a.Ads, int(a.GetLastTime())); err != nil {
+								log.Println(fmt.Sprintf("广告位缓存 %s保存异常 err:%s", sCode, err.Error()))
+							}
+							adInfoMap[sCode] = a.Handle()
+						}
+					}
+				}
+			}
 		}
-		json.Unmarshal(bytes, &AdInfo_Arr)
-		if len(AdInfo_Arr) > 0 {
-			now := time.Now()
-			for _, v := range AdInfo_Arr {
-				log.Println(v.S_id, "---", host, "----", strings.Contains(host, v.S_id))
-				if v.S_id != "" && host != "" {
-					//根据不同环境区分广告位信息 v.S_id 填充内容, 例:app-i2;app-a1
-					if !strings.Contains(host, v.S_id) {
+	}
+	return
+}
+
+// Handle 广告位信息处理
+func (a *AdFunc) Handle() (adInfos []AdInfo) {
+	var ads = []AdInfo{}
+	err := json.Unmarshal(*a.Ads, &ads)
+	if err == nil && len(ads) > 0 {
+		now := time.Now()
+		for _, v := range ads {
+			if v.S_id != "" && a.Host != "" {
+				//根据不同环境区分广告位信息 v.S_id 填充内容, 例:app-i2;app-a1
+				if !strings.Contains(a.Host, v.S_id) {
+					continue
+				}
+			}
+			if v.O_extend.StartTime != "" && len(strings.Split(v.O_extend.StartTime, "-")) == 6 {
+				if thisTime, err := time.ParseInLocation("2006-01-02-15-04-05", v.O_extend.StartTime, time.Local); err == nil {
+					//广告还未开始
+					if thisTime.Unix() > now.Unix() {
+						continue
+					}
+				}
+			}
+			if v.O_extend.EndTime != "" && len(strings.Split(v.O_extend.EndTime, "-")) == 6 {
+				if thisTime, err := time.ParseInLocation("2006-01-02-15-04-05", v.O_extend.EndTime, time.Local); err == nil {
+					//广告已经结束
+					if thisTime.Unix() < now.Unix() {
 						continue
 					}
 				}
-				if v.O_extend.StartTime != "" && len(strings.Split(v.O_extend.StartTime, "-")) == 6 {
-					if thisTime, err := time.ParseInLocation("2006-01-02-15-04-05", v.O_extend.StartTime, time.Local); err == nil {
-						//广告还未开始
-						if thisTime.Unix() > now.Unix() {
-							continue
+			}
+			//  广告位区分用户身份 user_attribute 身份不一致时过滤
+			if uas := strings.Split(v.O_extend.UserAttribute, "_"); v.O_extend.UserAttribute != "" && len(uas) > 0 { // 用下划线分割 例:"m_v"
+				var userFlag bool
+				attributeMap := a.GetUserAttribute() // 获取用户身份
+				if attributeMap != nil {
+					for _, aua := range uas {
+						if attributeMap[aua] {
+							userFlag = UB
+							break
 						}
 					}
 				}
-				if v.O_extend.EndTime != "" && len(strings.Split(v.O_extend.EndTime, "-")) == 6 {
-					if thisTime, err := time.ParseInLocation("2006-01-02-15-04-05", v.O_extend.EndTime, time.Local); err == nil {
-						//广告已经结束
-						if thisTime.Unix() < now.Unix() {
-							continue
+				if !userFlag {
+					continue
+				}
+			}
+			// 订单分类
+			if oas := strings.Split(v.O_extend.OrderAttribute, "_"); a.IsLogin && len(oas) > 0 && a.OrderCode != "" {
+				var userFlag bool
+				attributeMap := a.GetOrderAttribute() // 获取订单分类
+				if attributeMap != nil {
+					for _, aoa := range oas {
+						if attributeMap[aoa] {
+							userFlag = UB
+							break
 						}
 					}
 				}
-				res = append(res, v)
+				if !userFlag {
+					continue
+				}
 			}
+			adInfos = append(adInfos, v)
 		}
 	}
-	return res
+	return
 }
 
-// 获取当天剩余时间
-var (
-	timeOut int64 = 24 * 60 * 60
-)
-
-func GetLastTime() int64 {
+func (a *AdFunc) GetLastTime() int64 {
 	t := time.Now()
 	midnight := time.Date(t.Year(), t.Month(), t.Day()+1, 0, 0, 0, 0, t.Location())
 	if midnight.After(t) {
@@ -85,3 +175,85 @@ func GetLastTime() int64 {
 	}
 	return timeOut
 }
+
+// 获取订单分类
+func (a *AdFunc) GetOrderAttribute() (attributesMap map[string]bool) {
+	if a.OrderCode != "" {
+		attributesMap = map[string]bool{}
+		orderData := a.MySql.FindOne("dataexport_order", map[string]interface{}{"order_code": a.OrderCode}, "filter,product_type,vip_type", "")
+		if orderData == nil { //未找到订单
+			attributesMap[OrderAttributeNoHave] = UB
+			return
+		}
+		productType := qutil.ObjToString((*orderData)["product_type"])
+		vipType := qutil.IntAll((*orderData)["vip_type"])
+		switch productType {
+		case "VIP订阅":
+			switch vipType {
+			case 1: //续费
+				attributesMap[OrderAttributeVipRenew] = UB
+			case 2: //升级
+				attributesMap[OrderAttributeVipUpgrade] = UB
+			default: //默认购买
+				attributesMap[OrderAttributeVipBuy] = UB
+			}
+		case "大会员":
+			attributesMap[OrderAttributeBigMemberBuy] = UB
+		}
+		log.Println(productType, vipType)
+	}
+	return
+}
+
+// 获取用户身份信息  如果是符合多个身份就追加到一个列表里面
+func (a *AdFunc) GetUserAttribute() (attributesMap map[string]bool) {
+	attributesMap = map[string]bool{}
+	// 未登录用户
+	if !a.IsLogin {
+		attributesMap[UserAttributeGuest] = UB
+		return
+	}
+	ui := a.UserInfo
+	//文库会员
+	if ui.Data.Docs.Status > 0 {
+		attributesMap[UserAttributeDocsMember] = UB
+	}
+	if ui.Status <= 0 && ui.VipStatus <= 0 {
+		// 非超级订阅非大会员
+		attributesMap[UserAttributeNotMV] = UB
+		switch {
+		case ui.EntnicheStatus <= 0:
+			// 免费用户
+			attributesMap[UserAttributeFree] = UB
+		default:
+			// 商机管理
+			attributesMap[UserAttributeEntniche] = UB
+		}
+	}
+	if ui.Status > 0 {
+		// 大会员
+		attributesMap[UserAttributeMember] = UB
+		switch {
+		case ui.VipStatus > 0:
+			// 大会员且超级订阅
+			attributesMap[UserAttributeLimitMV] = UB
+		default:
+			// 大会员非超级订阅
+			attributesMap[UserAttributeLimitM] = UB
+		}
+	}
+	if ui.VipStatus > 0 {
+		// 超级订阅
+		attributesMap[UserAttributeVip] = UB
+		switch {
+		case ui.Status <= 0:
+			// 超级订阅非大会员
+			attributesMap[UserAttributeLimitV] = UB
+		}
+	}
+	if ui.EntnicheStatus > 0 {
+		// 商机管理用户
+		attributesMap[UserAttributeEntniche] = UB
+	}
+	return
+}

+ 2 - 1
common/src/qfw/util/jy/bigVipPower.go

@@ -97,7 +97,8 @@ const (
 func InitBigVipService(mysql *mysql.Mysql) {
 	serviceList := mysql.Find(BigmemberServiceTable, nil, "id,s_url_front,s_url_back", "id", -1, -1)
 	if serviceList == nil || len(*serviceList) == 0 {
-		panic(fmt.Sprintf("大会员初始权限失败,请检查mysql链接是否正常、查看%s表是否正常", BigmemberServiceTable))
+		var msg interface{} = fmt.Sprintf("大会员初始权限失败,请检查mysql链接是否正常、查看%s表是否正常", BigmemberServiceTable)
+		panic(msg)
 	}
 	FrontService, BackService = make(map[string][]int), make(map[string][]int)
 	for _, one := range *serviceList {

+ 1 - 0
common/src/qfw/util/jy/channel.go

@@ -38,6 +38,7 @@ type UserSource struct {
 	ChannelCode      string `json:"channel_code"`       //渠道代码
 	EncryptionUserId string `json:"encryption_user_id"` //用户加密id
 	CreateTime       string `json:"create_time"`        //创建时间
+	LoginCode        string `json:"login_code"`         //登录code;jy_pc_phone等
 	LoginWay         int    `json:"login_way"`          //登录方式;1:手机号密码登录;2:手机号验证码登录;3:微信登录;4:手机号一键登录
 	Platform         int    `json:"platform"`           //登录端;1:PC;2:WX;3:APP;4:H5
 	Ip               string `json:"ip"`                 //登录ip

+ 16 - 0
common/src/qfw/util/jy/jy.go

@@ -460,3 +460,19 @@ func KeywordsProcessing(keywords, sep string) string {
 	}
 	return strings.Join(newWords, sep)
 }
+
+// 行业分类 其它分类处理
+var industryQT = "其它"
+
+func IndustryHandle(industry string) (it []string) {
+	for _, v := range strings.Split(industry, ",") {
+		if strings.Contains(v, "其他") {
+			var iqt = industryQT
+			if len(strings.Split(v, "_")) > 1 {
+				iqt = fmt.Sprintf("%s_%s", strings.Split(v, "_")[0], industryQT)
+			}
+			it = append(it, iqt)
+		}
+	}
+	return
+}

+ 50 - 0
common/src/qfw/util/jy/ordercode.go

@@ -0,0 +1,50 @@
+package jy
+
+import (
+	qutil "app.yhyue.com/moapp/jybase/common"
+	"fmt"
+	"sync"
+	"time"
+)
+
+var (
+	VarOrderCode *orderCode
+)
+
+type orderCode struct {
+	Pool chan string
+	All  *sync.Map
+	Lock *sync.Mutex
+}
+
+func (o *orderCode) gc() {
+	VarOrderCode.All.Range(func(key, value interface{}) bool {
+		if time.Now().Day() != value.(int) {
+			VarOrderCode.All.Delete(key)
+		}
+		return true
+	})
+	time.AfterFunc(24*time.Hour, o.gc)
+}
+func OrderCodePoolInit() {
+	VarOrderCode = &orderCode{
+		Pool: make(chan string, 20),
+		All:  &sync.Map{},
+		Lock: &sync.Mutex{},
+	}
+	VarOrderCode.gc()
+	for i := 0; i < 10; i++ {
+		go func() {
+			VarOrderCode.Lock.Lock()
+			defer VarOrderCode.Lock.Unlock()
+			for {
+				o := fmt.Sprintf("%d%s", time.Now().Unix()+900000000, qutil.GetRandom(2))
+				if _, ok := VarOrderCode.All.Load(o); ok {
+					continue
+				}
+				VarOrderCode.All.Store(o, time.Now().Day())
+				VarOrderCode.Pool <- o
+			}
+		}()
+	}
+}

+ 40 - 19
common/src/qfw/util/jy/subScribe.go

@@ -6,6 +6,7 @@ import (
 	"app.yhyue.com/moapp/jybase/go-xweb/httpsession"
 	"app.yhyue.com/moapp/jybase/go-xweb/log"
 	"app.yhyue.com/moapp/jybase/mongodb"
+	"time"
 )
 
 func GetSubScribeInfo(session *httpsession.Session, mg mongodb.MongodbSim, types, appid string) *map[string]interface{} {
@@ -25,31 +26,31 @@ func GetSubScribeInfo(session *httpsession.Session, mg mongodb.MongodbSim, types
 		}
 	}
 	object := &map[string]interface{}{}
-	jyData := &map[string]interface{}{}
+	var jyData map[string]interface{}
 	switch types {
 	case MemberFlag:
 		//大会员
 		if positionType == 0 {
 			//个人
 			if (*data)["o_member_jy"] != nil {
-				jyData = common.ObjToMap((*data)["o_member_jy"])
+				jyData = *common.ObjToMap((*data)["o_member_jy"])
 			}
 		} else {
-			jyData = EntnicheSub(entUserId, entId, 1, mg)
+			jyData = *EntnicheSub(entUserId, entId, 1, mg)
 		}
 	case EntnicheFlag:
 		//商机管理
-		jyData = EntnicheSub(entUserId, entId, 0, mg)
+		jyData = *EntnicheSub(entUserId, entId, 0, mg)
 		log.Println("~~~", jyData)
 	case SubVipFlag:
 		//超级订阅
 		if positionType == 0 {
 			if (*data)["o_vipjy"] != nil {
 				//个人
-				jyData = common.ObjToMap((*data)["o_vipjy"])
+				jyData = *common.ObjToMap((*data)["o_vipjy"])
 			}
 		} else {
-			jyData = EntnicheSub(entUserId, entId, 1, mg)
+			jyData = *EntnicheSub(entUserId, entId, 1, mg)
 		}
 	case SubFreeFlag:
 		if positionType == 0 {
@@ -72,40 +73,40 @@ func GetSubScribeInfo(session *httpsession.Session, mg mongodb.MongodbSim, types
 				}
 			}
 		} else {
-			jyData = EntnicheSub(entUserId, entId, 2, mg)
+			jyData = *EntnicheSub(entUserId, entId, 2, mg)
 		}
 	}
 	if jyData != nil {
-		object = format(jyData)
+		object = format(&jyData)
 	}
 	return object
 }
 
-//商机管理订阅设置
+// 商机管理订阅设置
 func EntnicheSub(entUserId, entId int64, types int64, mg mongodb.MongodbSim) *map[string]interface{} {
-	object := &map[string]interface{}{}
+	//object := &map[string]interface{}{}
 	entnicheJy := &map[string]interface{}{}
 	res, _ := mg.FindOne("entniche_rule", map[string]interface{}{
 		"i_userid": entUserId,
 		"i_entid":  entId,
-		"types":    types,
+		"i_type":   types,
 	})
 	if types == 2 {
 		if (*res)["o_entniche"] != nil {
-			ojy := common.ObjToMap((*res)["o_jy"])
-			object = ojy
-			if (*ojy)["a_key"] != nil {
+			ojy := common.ObjToMap((*res)["o_entniche"])
+			entnicheJy = ojy
+			if _, ok := (*ojy)["a_key"]; ok {
 				akey := common.ObjArrToMapArr((*ojy)["a_key"].([]interface{}))
-				(*object)["a_items"] = []map[string]interface{}{ //转换至和其它结构一致
+				(*entnicheJy)["a_items"] = []interface{}{ //转换至和其它结构一致
 					map[string]interface{}{
 						"a_key": akey,
 					},
 				}
 			}
-			if (*ojy)["o_area"] == nil {
-				(*object)["o_area"] = map[string]interface{}{}
+			if _, ok := (*ojy)["o_area"]; !ok {
+				(*entnicheJy)["o_area"] = map[string]interface{}{}
 			} else {
-				(*object)["o_area"] = (*ojy)["o_area"]
+				(*entnicheJy)["o_area"] = (*ojy)["o_area"]
 			}
 		}
 	} else {
@@ -115,7 +116,7 @@ func EntnicheSub(entUserId, entId int64, types int64, mg mongodb.MongodbSim) *ma
 	return entnicheJy
 }
 
-//格式化数据 大会员/超级订阅/商机管理 结构一致 关键词格式化
+// 格式化数据 大会员/超级订阅/商机管理 结构一致 关键词格式化
 func format(data *map[string]interface{}) *map[string]interface{} {
 	if data == nil {
 		return nil
@@ -156,3 +157,23 @@ func format(data *map[string]interface{}) *map[string]interface{} {
 	}
 	return data
 }
+
+// 用户注册日志保存
+func SaveUserLog(mg mongodb.MongodbSim, userid, phone, way, system, source, openid, search_engine, promotion, ip, user_agent, site, event string) {
+	data := map[string]interface{}{
+		"userid":        userid,
+		"phone":         phone,
+		"way":           way,
+		"system":        system,
+		"source":        source,
+		"create_time":   time.Now().Format("2006-01-02 15:04:05"),
+		"openid":        openid,
+		"search_engine": search_engine,
+		"promotion":     promotion,
+		"ip":            ip,
+		"user_agent":    user_agent,
+		"site":          site,
+		"event":         event,
+	}
+	mg.Save("register_log", data)
+}

+ 74 - 67
go.mod

@@ -1,26 +1,30 @@
 module app.yhyue.com/moapp/jypkg
 
-go 1.18
+go 1.20
 
 require (
 	app.yhyue.com/moapp/jyMarketing v0.0.2-0.20230304035551-21bb1eedf547
-	app.yhyue.com/moapp/jybase v0.0.0-20230718012114-37013054344b
-	app.yhyue.com/moapp/message v0.0.0-20221223100203-6402e389d9ae
-	bp.jydev.jianyu360.cn/BaseService/entManageApplication v0.0.0-20230214091519-89a98c01ab0e
-	bp.jydev.jianyu360.cn/BaseService/powerCheckCenter v0.0.0-20231219095433-7e7d4aa59822
-	bp.jydev.jianyu360.cn/BaseService/resourceCenter v0.0.8
-	bp.jydev.jianyu360.cn/BaseService/userCenter v1.2.15-0.20230925060020-8e4db0f1e13e
+	app.yhyue.com/moapp/jyPoints v1.1.2-0.20231020023521-1a4b1bbf9736
+	app.yhyue.com/moapp/jybase v0.0.0-20240226084952-7e7b38ef8a66
+	app.yhyue.com/moapp/message v0.0.0-20231204024949-8c7145bfc161
+	bp.jydev.jianyu360.cn/BaseService/entManageApplication v0.0.0-20231226074509-942d80dc34eb
+	bp.jydev.jianyu360.cn/BaseService/jyMicroservices v0.0.2
+	bp.jydev.jianyu360.cn/BaseService/powerCheckCenter v0.0.0-20240607062231-ae1d02891843
+	bp.jydev.jianyu360.cn/BaseService/resourceCenter v0.1.3
+	bp.jydev.jianyu360.cn/BaseService/userCenter v1.2.18
+	github.com/gogf/gf/v2 v2.7.0
 	github.com/nsqio/go-nsq v1.1.0
 	github.com/robfig/cron v1.2.0
 	github.com/tealeg/xlsx v1.0.5
 	github.com/thinxer/go-word2vec v0.0.0-20150917053916-5c19ec7379ed
-	github.com/zeromicro/go-zero v1.5.3
-	go.mongodb.org/mongo-driver v1.11.6
-	jygit.jydev.jianyu360.cn/ApplicationCenter/publicService v0.0.0-20231017031425-45003ca9f35a
+	github.com/zeromicro/go-zero v1.6.4
+	go.mongodb.org/mongo-driver v1.14.0
+	jygit.jydev.jianyu360.cn/ApplicationCenter/publicService v0.0.0-20231023011746-38dc3b6aded8
 )
 
 require (
 	app.yhyue.com/moapp/esv1 v0.0.0-20220414031211-3da4123e648d // indirect
+	filippo.io/edwards25519 v1.1.0 // indirect
 	github.com/beorn7/perks v1.0.1 // indirect
 	github.com/cenkalti/backoff/v4 v4.2.1 // indirect
 	github.com/cespare/xxhash/v2 v2.2.0 // indirect
@@ -28,97 +32,100 @@ require (
 	github.com/coreos/go-systemd/v22 v22.5.0 // indirect
 	github.com/davecgh/go-spew v1.1.1 // indirect
 	github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
-	github.com/emicklei/go-restful/v3 v3.9.0 // indirect
-	github.com/fatih/color v1.15.0 // indirect
+	github.com/emicklei/go-restful/v3 v3.11.0 // indirect
+	github.com/fatih/color v1.16.0 // indirect
 	github.com/garyburd/redigo v1.6.2 // indirect
-	github.com/go-logr/logr v1.2.4 // indirect
+	github.com/go-logr/logr v1.3.0 // indirect
 	github.com/go-logr/stdr v1.2.2 // indirect
 	github.com/go-openapi/jsonpointer v0.19.6 // indirect
-	github.com/go-openapi/jsonreference v0.20.1 // indirect
-	github.com/go-openapi/swag v0.22.3 // indirect
-	github.com/go-redis/redis/v8 v8.11.5 // indirect
-	github.com/go-sql-driver/mysql v1.7.1 // indirect
+	github.com/go-openapi/jsonreference v0.20.2 // indirect
+	github.com/go-openapi/swag v0.22.4 // indirect
+	github.com/go-sql-driver/mysql v1.8.1 // indirect
 	github.com/gogo/protobuf v1.3.2 // indirect
 	github.com/golang/mock v1.6.0 // indirect
-	github.com/golang/protobuf v1.5.3 // indirect
+	github.com/golang/protobuf v1.5.4 // indirect
 	github.com/golang/snappy v0.0.4 // indirect
 	github.com/gomodule/redigo v2.0.0+incompatible // indirect
-	github.com/google/gnostic v0.5.7-v3refs // indirect
-	github.com/google/go-cmp v0.5.9 // indirect
+	github.com/google/gnostic-models v0.6.8 // indirect
+	github.com/google/go-cmp v0.6.0 // indirect
 	github.com/google/gofuzz v1.2.0 // indirect
-	github.com/grpc-ecosystem/grpc-gateway/v2 v2.15.0 // indirect
+	github.com/google/uuid v1.6.0 // indirect
+	github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0 // indirect
 	github.com/howeyc/fsnotify v0.9.0 // indirect
 	github.com/jinzhu/inflection v1.0.0 // indirect
 	github.com/jinzhu/now v1.1.1 // indirect
 	github.com/josharian/intern v1.0.0 // indirect
 	github.com/json-iterator/go v1.1.12 // indirect
-	github.com/klauspost/compress v1.15.15 // indirect
+	github.com/klauspost/compress v1.16.7 // indirect
 	github.com/mailru/easyjson v0.7.7 // indirect
 	github.com/mattn/go-colorable v0.1.13 // indirect
-	github.com/mattn/go-isatty v0.0.17 // indirect
-	github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
+	github.com/mattn/go-isatty v0.0.20 // indirect
+	github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect
 	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
 	github.com/modern-go/reflect2 v1.0.2 // indirect
 	github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe // indirect
 	github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
 	github.com/olivere/elastic v6.2.37+incompatible // indirect
 	github.com/olivere/elastic/v7 v7.0.22 // indirect
-	github.com/openzipkin/zipkin-go v0.4.1 // indirect
-	github.com/pelletier/go-toml/v2 v2.0.8 // indirect
+	github.com/openzipkin/zipkin-go v0.4.2 // indirect
+	github.com/pelletier/go-toml/v2 v2.2.0 // indirect
 	github.com/pkg/errors v0.9.1 // indirect
-	github.com/prometheus/client_golang v1.15.1 // indirect
-	github.com/prometheus/client_model v0.3.0 // indirect
-	github.com/prometheus/common v0.42.0 // indirect
-	github.com/prometheus/procfs v0.9.0 // indirect
+	github.com/prometheus/client_golang v1.18.0 // indirect
+	github.com/prometheus/client_model v0.5.0 // indirect
+	github.com/prometheus/common v0.45.0 // indirect
+	github.com/prometheus/procfs v0.12.0 // indirect
+	github.com/redis/go-redis/v9 v9.4.0 // indirect
 	github.com/spaolacci/murmur3 v1.1.0 // indirect
 	github.com/xdg-go/pbkdf2 v1.0.0 // indirect
-	github.com/xdg-go/scram v1.1.1 // indirect
-	github.com/xdg-go/stringprep v1.0.3 // indirect
-	github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect
+	github.com/xdg-go/scram v1.1.2 // indirect
+	github.com/xdg-go/stringprep v1.0.4 // indirect
+	github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a // indirect
 	github.com/ziutek/blas v0.0.0-20190227122918-da4ca23e90bb // indirect
-	go.etcd.io/etcd/api/v3 v3.5.9 // indirect
-	go.etcd.io/etcd/client/pkg/v3 v3.5.9 // indirect
-	go.etcd.io/etcd/client/v3 v3.5.9 // indirect
-	go.opentelemetry.io/otel v1.15.1 // indirect
-	go.opentelemetry.io/otel/exporters/jaeger v1.15.1 // indirect
-	go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.15.1 // indirect
-	go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.15.1 // indirect
-	go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.15.1 // indirect
-	go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.15.1 // indirect
-	go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.14.0 // indirect
-	go.opentelemetry.io/otel/exporters/zipkin v1.15.1 // indirect
-	go.opentelemetry.io/otel/sdk v1.15.1 // indirect
-	go.opentelemetry.io/otel/trace v1.15.1 // indirect
-	go.opentelemetry.io/proto/otlp v0.19.0 // indirect
+	go.etcd.io/etcd/api/v3 v3.5.13 // indirect
+	go.etcd.io/etcd/client/pkg/v3 v3.5.13 // indirect
+	go.etcd.io/etcd/client/v3 v3.5.13 // indirect
+	go.opentelemetry.io/otel v1.19.0 // indirect
+	go.opentelemetry.io/otel/exporters/jaeger v1.17.0 // indirect
+	go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 // indirect
+	go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0 // indirect
+	go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 // indirect
+	go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.19.0 // indirect
+	go.opentelemetry.io/otel/exporters/zipkin v1.19.0 // indirect
+	go.opentelemetry.io/otel/metric v1.19.0 // indirect
+	go.opentelemetry.io/otel/sdk v1.19.0 // indirect
+	go.opentelemetry.io/otel/trace v1.19.0 // indirect
+	go.opentelemetry.io/proto/otlp v1.0.0 // indirect
 	go.uber.org/atomic v1.10.0 // indirect
-	go.uber.org/automaxprocs v1.5.2 // indirect
+	go.uber.org/automaxprocs v1.5.3 // indirect
 	go.uber.org/multierr v1.9.0 // indirect
 	go.uber.org/zap v1.24.0 // indirect
-	golang.org/x/crypto v0.6.0 // indirect
-	golang.org/x/net v0.10.0 // indirect
-	golang.org/x/oauth2 v0.7.0 // indirect
-	golang.org/x/sync v0.1.0 // indirect
-	golang.org/x/sys v0.8.0 // indirect
-	golang.org/x/term v0.8.0 // indirect
-	golang.org/x/text v0.9.0 // indirect
-	golang.org/x/time v0.3.0 // indirect
-	google.golang.org/appengine v1.6.7 // indirect
-	google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect
-	google.golang.org/grpc v1.56.1 // indirect
-	google.golang.org/protobuf v1.31.0 // indirect
+	golang.org/x/crypto v0.22.0 // indirect
+	golang.org/x/net v0.24.0 // indirect
+	golang.org/x/oauth2 v0.17.0 // indirect
+	golang.org/x/sync v0.6.0 // indirect
+	golang.org/x/sys v0.19.0 // indirect
+	golang.org/x/term v0.19.0 // indirect
+	golang.org/x/text v0.14.0 // indirect
+	golang.org/x/time v0.5.0 // indirect
+	google.golang.org/appengine v1.6.8 // indirect
+	google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect
+	google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de // indirect
+	google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de // indirect
+	google.golang.org/grpc v1.63.2 // indirect
+	google.golang.org/protobuf v1.33.0 // indirect
 	gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
 	gopkg.in/inf.v0 v0.9.1 // indirect
 	gopkg.in/yaml.v2 v2.4.0 // indirect
 	gopkg.in/yaml.v3 v3.0.1 // indirect
 	gorm.io/driver/mysql v1.0.5 // indirect
 	gorm.io/gorm v1.21.3 // indirect
-	k8s.io/api v0.26.3 // indirect
-	k8s.io/apimachinery v0.27.0-alpha.3 // indirect
-	k8s.io/client-go v0.26.3 // indirect
-	k8s.io/klog/v2 v2.90.1 // indirect
-	k8s.io/kube-openapi v0.0.0-20230307230338-69ee2d25a840 // indirect
-	k8s.io/utils v0.0.0-20230209194617-a36077c30491 // indirect
+	k8s.io/api v0.29.3 // indirect
+	k8s.io/apimachinery v0.29.3 // indirect
+	k8s.io/client-go v0.29.3 // indirect
+	k8s.io/klog/v2 v2.110.1 // indirect
+	k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 // indirect
+	k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect
 	sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
-	sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
+	sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
 	sigs.k8s.io/yaml v1.3.0 // indirect
 )

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 871 - 43
go.sum


+ 61 - 0
identity/identity.go

@@ -1,6 +1,8 @@
 package identity
 
 import (
+	"fmt"
+	"sort"
 	"strconv"
 
 	. "app.yhyue.com/moapp/jybase/common"
@@ -24,6 +26,7 @@ type IdentityInfo struct {
 	EntRole      int64  //管理员角色
 	EntNicheDis  int64  //商机分配角色
 	EntDeptId    int64  //部门id
+	EntUserRole  string //
 }
 
 func NewIdentityInfo(i *pb.Identity) *IdentityInfo {
@@ -41,6 +44,7 @@ func NewIdentityInfo(i *pb.Identity) *IdentityInfo {
 		EntRole:      i.EntRole,
 		EntNicheDis:  i.EntNicheDis,
 		EntDeptId:    i.EntDeptId,
+		EntUserRole:  i.EntUserRole,
 	}
 }
 
@@ -72,6 +76,7 @@ func (i *IdentityInfo) Switch(sess *httpsession.Session, mgo *MongodbSim) bool {
 		m["entRole"] = i.EntRole
 		m["entNicheDis"] = i.EntNicheDis
 		m["entDeptId"] = i.EntDeptId
+		m["entUserRole"] = i.EntUserRole
 		ok = true
 	}
 	sess.SetMultiple(m)
@@ -89,6 +94,7 @@ func SwitchToBest(userId int64, sess *httpsession.Session, mgd *Middleground, mg
 	if list == nil || len(list) == 0 {
 		return -1, false
 	}
+	//选择上次用户身份
 	if isSelectLast {
 		if mgoUserId, _ := sess.Get("mgoUserId").(string); mgoUserId != "" {
 			user, ok := mgo.FindById("user", mgoUserId, `{"login_positionid":1}`)
@@ -103,6 +109,12 @@ func SwitchToBest(userId int64, sess *httpsession.Session, mgd *Middleground, mg
 			}
 		}
 	}
+
+	// 切换至最优付费账户
+	if bestIdentity := getBestChoosePosition(sess, mgd, list); bestIdentity != nil {
+		return bestIdentity.PositionId, NewIdentityInfo(bestIdentity).Switch(sess, mgo)
+	}
+
 	reqIds := []int64{}
 	for _, v := range list {
 		if v.PositionType == 1 {
@@ -125,3 +137,52 @@ func SwitchToBest(userId int64, sess *httpsession.Session, mgd *Middleground, mg
 	}
 	return -1, false
 }
+
+// getBestChoosePosition
+// 首次登录身份选择 【p387多个身份都有付费产品权限,则先按照产品优先级进行身份的选择,即大会员>商机管理>超级订阅>省份订阅包,如若多个身份的产品权限一致,则优先选择“服务结束时间”晚的身份。】
+func getBestChoosePosition(sess *httpsession.Session, mgd *Middleground, positionList []*pb.Identity) *pb.Identity {
+	var (
+		appId      = "10000"
+		mgoUserId  = ObjToString(sess.Get("mgoUserId"))
+		baseUserId = Int64All(sess.Get("base_user_id"))
+
+		scorePositionMap = map[string]*pb.Identity{}
+		scoreArr         []string
+	)
+
+	for _, v := range positionList {
+		var (
+			endTime  int64
+			flag     int64
+			weight   string
+			powerRes = mgd.PowerCheckCenter.Check(appId, mgoUserId, baseUserId, v.AccountId, v.EntId, v.PositionType, v.PositionId)
+		)
+
+		if powerRes.Member.Status > 0 {
+			flag, endTime = 9, powerRes.Member.GetEndTime()
+		} else if powerRes.Entniche.Status > 0 {
+			flag, endTime = 8, powerRes.Entniche.GetEndTime()
+		} else if powerRes.Vip.Status > 0 {
+			flag, endTime = 7, powerRes.Vip.GetEndTime()
+		} else if powerRes.Free.PpStatus > 0 {
+			flag, endTime = 6, powerRes.Free.GetPpEndTime()
+		}
+		if flag > 0 {
+			weight = fmt.Sprintf("%d%d", flag, endTime)
+			scoreArr = append(scoreArr, weight)
+			scorePositionMap[weight] = v
+		}
+	}
+
+	var (
+		sLen = len(scoreArr)
+		pos  = sLen - 1
+	)
+	if sLen > 0 {
+		if sLen > 1 { // 当有多个付费身份时;根据权重字符串排序
+			sort.Strings(scoreArr)
+		}
+		return scorePositionMap[scoreArr[pos]]
+	}
+	return nil
+}

+ 104 - 0
middleground/base.go

@@ -0,0 +1,104 @@
+// 微服务 基础服务 jyBase
+package middleground
+
+import (
+	bbc "bp.jydev.jianyu360.cn/BaseService/jyMicroservices/jyBXBase/rpc/bxbase"
+	"bp.jydev.jianyu360.cn/BaseService/jyMicroservices/jyBXBase/rpc/type/bxbase"
+	"context"
+	"github.com/zeromicro/go-zero/core/discov"
+	"github.com/zeromicro/go-zero/zrpc"
+	"log"
+)
+
+type jyBase struct {
+	hosts  []string
+	key    string
+	client zrpc.Client
+}
+
+func newBase(hosts []string, key string) *jyBase {
+	b := &jyBase{
+		hosts: hosts,
+		key:   key,
+	}
+	b.client = b.NewClient()
+	return b
+}
+
+func (b *jyBase) NewClient() zrpc.Client {
+	if b.client != nil && b.client.Conn() != nil {
+		return b.client
+	}
+	client, err := zrpc.NewClient(zrpc.RpcClientConf{
+		Etcd: discov.EtcdConf{
+			Hosts: b.hosts,
+			Key:   b.key,
+		},
+	})
+	if err != nil {
+		log.Println(err)
+		return nil
+	}
+	b.client = client
+	return client
+}
+
+// 搜索标签 过滤
+func (b *jyBase) CheckSearch(asr *bxbase.AddSearchReq) *bxbase.CheckRes {
+	client := b.NewClient()
+	if client == nil {
+		return nil
+	}
+	//defer client.Conn().Close()
+	resp, err := bbc.NewBxbase(client).CheckSearch(context.Background(), asr)
+	if err != nil {
+		log.Println(err)
+		return nil
+	}
+	return resp
+}
+
+// 添加搜索标签
+func (b *jyBase) AddSearch(asr *bxbase.AddSearchReq) *bxbase.CommonRes {
+	client := b.NewClient()
+	if client == nil {
+		return nil
+	}
+	//defer client.Conn().Close()
+	resp, err := bbc.NewBxbase(client).AddSearch(context.Background(), asr)
+	if err != nil {
+		log.Println(err)
+		return nil
+	}
+	return resp
+}
+
+// 删除搜索标签
+func (b *jyBase) DelSearch(dsr *bxbase.DelSearchReq) *bxbase.CommonRes {
+	client := b.NewClient()
+	if client == nil {
+		return nil
+	}
+	//defer client.Conn().Close()
+	resp, err := bbc.NewBxbase(client).DelSearch(context.Background(), dsr)
+	if err != nil {
+		log.Println(err)
+		return nil
+	}
+	return resp
+}
+
+// 搜索标签
+func (b *jyBase) ShowSearch(ssr *bxbase.ShowSearchReq) *bxbase.ShowSearchRes {
+	client := b.NewClient()
+	if client == nil {
+		return nil
+	}
+	//defer client.Conn().Close()
+	resp, err := bbc.NewBxbase(client).ShowSearch(context.Background(), ssr)
+	if err != nil {
+		log.Println(err)
+		return nil
+	}
+	return resp
+}

+ 107 - 0
middleground/jypoints.go

@@ -0,0 +1,107 @@
+package middleground
+
+import (
+	"app.yhyue.com/moapp/jyPoints/rpc/integral"
+	"app.yhyue.com/moapp/jyPoints/rpc/integralclient"
+	"context"
+	"fmt"
+	"github.com/zeromicro/go-zero/core/discov"
+	"github.com/zeromicro/go-zero/zrpc"
+	"log"
+)
+
+type jyPoints struct {
+	hosts  []string
+	key    string
+	client zrpc.Client
+}
+
+func newJyPoints(hosts []string, key string) *jyPoints {
+	r := &jyPoints{
+		hosts: hosts,
+		key:   key,
+	}
+	r.client = r.NewClient()
+	return r
+}
+
+func (r *jyPoints) NewClient() zrpc.Client {
+	if r.client != nil && r.client.Conn() != nil {
+		return r.client
+	}
+	client, err := zrpc.NewClient(zrpc.RpcClientConf{
+		Etcd: discov.EtcdConf{
+			Hosts: r.hosts,
+			Key:   r.key,
+		},
+	})
+	if err != nil {
+		log.Println(err)
+		return nil
+	}
+	r.client = client
+	return client
+}
+
+// 积分消费2008
+func (r *jyPoints) PointConsume(userId, appId, endDate, sourceType, abstract string, point, pointType int64, operationType bool) (resp *integral.Resp, err error) {
+	client := r.NewClient()
+	if client == nil {
+		err = fmt.Errorf("jyPoint client err 01")
+		return
+	}
+	resp, err = integralclient.NewIntegral(client).IntegralConsume(context.Background(), &integral.Req{
+		UserId:        userId,
+		AppId:         appId,
+		EndDate:       endDate,
+		SourceType:    sourceType,
+		Point:         point,
+		PointType:     pointType,
+		Abstract:      abstract,
+		OperationType: operationType,
+	})
+	log.Println("消费剑鱼币 请求积分rpc 返回内容:", resp)
+	return
+}
+
+// 积分新增
+func (r *jyPoints) PointHarvest(userId, appId, endDate, sourceType, abstract string, point, pointType int64, operationType bool) (resp *integral.Resp, err error) {
+	client := r.NewClient()
+	if client == nil {
+		err = fmt.Errorf("jyPoint client err 02")
+		return
+	}
+	var (
+		ctx = context.Background()
+	)
+	resp, err = integralclient.NewIntegral(client).IntegralHarvest(ctx, &integral.Req{
+		UserId:        userId,
+		AppId:         appId,
+		EndDate:       endDate,
+		SourceType:    sourceType,
+		Point:         point,
+		PointType:     pointType,
+		Abstract:      abstract,
+		OperationType: operationType,
+	})
+	log.Println("奖励剑鱼币 请求积分rpc 返回内容:", resp)
+	return
+}
+
+// 积分查询
+func (r *jyPoints) PointIntegralBalance(userId, appId string) (resp *integral.Resp, err error) {
+	client := r.NewClient()
+	if client == nil {
+		err = fmt.Errorf("jyPoint client err 03")
+		return
+	}
+	var (
+		ctx = context.Background()
+	)
+	resp, err = integralclient.NewIntegral(client).IntegralBalanceCheck(ctx, &integral.Req{
+		UserId: userId,
+		AppId:  appId,
+	})
+	log.Println("奖励剑鱼币 请求积分rpc 返回内容:", resp)
+	return
+}

+ 18 - 0
middleground/middleground.go

@@ -8,6 +8,8 @@ type Middleground struct {
 	EntManageApplication *entManageApplication
 	ActivityCenter       *activity
 	Publicservice        *publicService
+	JyPoints             *jyPoints
+	JyBase               *jyBase
 }
 
 func NewMiddleground(hosts []string) *Middleground {
@@ -15,30 +17,46 @@ func NewMiddleground(hosts []string) *Middleground {
 		hosts: hosts,
 	}
 }
+
 func (m *Middleground) RegUserCenter(key string) *Middleground {
 	m.UserCenter = newUserCenter(m.hosts, key)
 	return m
 }
+
 func (m *Middleground) RegResourceCenter(key string) *Middleground {
 	m.ResourceCenter = newResourceCenter(m.hosts, key)
 	return m
 }
+
 func (m *Middleground) RegPowerCheckCenter(key string) *Middleground {
 	m.PowerCheckCenter = newPowerCheckCenter(m.hosts, key)
 	return m
 }
+
 func (m *Middleground) RegEntManageApplication(key string) *Middleground {
 	m.EntManageApplication = newEntManageApplication(m.hosts, key)
 	return m
 }
+
 func (m *Middleground) RegActivity(key string) *Middleground {
 	m.ActivityCenter = newActivity(m.hosts, key)
 	return m
 }
+
 func (m *Middleground) RegPublicservice(key string) *Middleground {
 	m.Publicservice = newPublicservice(m.hosts, key)
 	return m
 }
+
+func (m *Middleground) RegJyPoints(key string) *Middleground {
+	m.JyPoints = newJyPoints(m.hosts, key)
+	return m
+}
+
+func (m *Middleground) RegJyBase(key string) *Middleground {
+	m.JyBase = newBase(m.hosts, key)
+	return m
+}
 func main() {
 	//userId: 63d498bb6ae0e1ea2170e03d -baseUserId: 366251 -accountId: 13485 -entId: 15419 -positionType: 0 -baseUserId: 366251 -accountId: 13485 -entId: 15419 -positionType: 0 -positionId: 932
 	NewMiddleground([]string{"192.168.3.206:2379"}).RegPowerCheckCenter("powercheck.rpc")

+ 19 - 2
public/dataexport.go

@@ -106,6 +106,8 @@ type BidSearchExport struct {
 	Industry        string //选中的行业
 	SelectType      string //标题 or 全文
 	Winner          string //中标单位
+	Buyer           string `json:"buyer"`  //招标单位(采购单位)
+	Agency          string `json:"agency"` //招标代理机构(采购单位)
 	Buyerclass      string //采购单位行业
 	Hasbuyertel     string //是否有采购电话
 	Haswinnertel    string //是否有中标电话
@@ -124,8 +126,11 @@ type BidSearchExport struct {
 
 func (this *BidSearchExport) PassBidSearchExport(Sysconfig map[string]interface{}) (returnData map[string]interface{}) {
 	defer util.Catch()
-	areaSave, industrySave, citySave, districtSave := []string{}, []string{}, []string{}, []string{}
-	winnerSave, buyerclassSave := []string{}, []string{}
+
+	var (
+		areaSave, industrySave, citySave, districtSave    = []string{}, []string{}, []string{}, []string{}
+		winnerSave, buyerSave, agencySave, buyerclassSave = []string{}, []string{}, []string{}, []string{}
+	)
 	publishtimeSave := this.Publishtime
 	if len(this.Area) > 0 {
 		areaSave = strings.Split(this.Area, ",")
@@ -138,6 +143,10 @@ func (this *BidSearchExport) PassBidSearchExport(Sysconfig map[string]interface{
 	}
 	if len(this.Industry) > 0 {
 		industrySave = strings.Split(this.Industry, ",")
+		//P510 行业:其它
+		if qt := jy.IndustryHandle(strings.Join(industrySave, "")); len(qt) > 0 {
+			industrySave = append(industrySave, qt...)
+		}
 	}
 	if len(this.Buyerclass) > 0 {
 		buyerclassSave = strings.Split(this.Buyerclass, ",")
@@ -146,6 +155,12 @@ func (this *BidSearchExport) PassBidSearchExport(Sysconfig map[string]interface{
 	if len(this.Winner) > 0 {
 		winnerSave = strings.Split(this.Winner, ",")
 	}
+	if len(this.Buyer) > 0 {
+		buyerSave = strings.Split(this.Buyer, ",")
+	}
+	if len(this.Agency) > 0 {
+		agencySave = strings.Split(this.Agency, ",")
+	}
 
 	KeyWordSave := []dataexport.KeyWord{}
 	if len(this.Keywords) > 0 || len(this.AdditionalWords) > 0 {
@@ -210,6 +225,8 @@ func (this *BidSearchExport) PassBidSearchExport(Sysconfig map[string]interface{
 		"selectType":   this.SelectType,
 		"buyerclass":   buyerclassSave,
 		"winner":       winnerSave,
+		"buyer":        buyerSave,
+		"agency":       agencySave,
 		"hasBuyertel":  this.Hasbuyertel,
 		"hasWinnertel": this.Haswinnertel,
 		"fileExists":   this.FileExists,

+ 15 - 8
public/db.go

@@ -5,7 +5,6 @@ import (
 
 	util "app.yhyue.com/moapp/jybase/common"
 	elastic "app.yhyue.com/moapp/jybase/es"
-	es "app.yhyue.com/moapp/jybase/esv7"
 	m "app.yhyue.com/moapp/jybase/mongodb"
 	"app.yhyue.com/moapp/jybase/mysql"
 	"app.yhyue.com/moapp/jybase/redis"
@@ -25,6 +24,7 @@ var (
 	//Mgo_Qyfw    m.MongodbSim
 	Other elastic.Es
 	Free  elastic.Es //登录后的免费用户搜索使用
+	Doc   elastic.Es
 )
 
 type dbConf struct {
@@ -38,9 +38,9 @@ type dbConf struct {
 	}
 	Elasticsearch struct {
 		Main  *esConf
-		Doc   *esConf
 		Other *esConf
 		Free  *esConf
+		Doc   *esConf
 	}
 	Redis struct {
 		Main  *redisConf
@@ -93,12 +93,6 @@ func init() {
 			log.Println("初始化 elasticsearch")
 		}
 
-		if DbConf.Elasticsearch.Doc != nil {
-			es.InitElasticSizeByAuth(DbConf.Elasticsearch.Doc.Address, DbConf.Elasticsearch.Doc.Size,
-				DbConf.Elasticsearch.Doc.UserName, DbConf.Elasticsearch.Doc.Password)
-			log.Println("初始化 doc elasticsearch")
-		}
-
 		if DbConf.Elasticsearch.Other != nil {
 			Other = &elastic.EsV7{
 				Address:  DbConf.Elasticsearch.Other.Address,
@@ -123,6 +117,19 @@ func init() {
 			log.Println("初始化 Free elasticsearch")
 		}
 
+		if DbConf.Elasticsearch.Doc != nil {
+			//es.InitElasticSizeByAuth(DbConf.Elasticsearch.Doc.Address, DbConf.Elasticsearch.Doc.Size,
+			//	DbConf.Elasticsearch.Doc.UserName, DbConf.Elasticsearch.Doc.Password)
+			Doc = &elastic.EsV7{
+				Address:  DbConf.Elasticsearch.Doc.Address,
+				UserName: DbConf.Elasticsearch.Doc.UserName,
+				Password: DbConf.Elasticsearch.Doc.Password,
+				Size:     DbConf.Elasticsearch.Doc.Size,
+			}
+			Doc.Init()
+			log.Println("初始化 doc elasticsearch")
+		}
+
 		//初始化redis
 		if DbConf.Redis.Main != nil {
 			log.Println("初始化 redis")

Vissa filer visades inte eftersom för många filer har ändrats