Parcourir la source

feat:采购单位搜索

fuwencai il y a 2 ans
Parent
commit
a5a91c205e

+ 7 - 8
jyBXBuyer/api/bxbuyer.api

@@ -12,20 +12,19 @@ type (
 		Province       []string `json:"province,optional"`       //省份
 		City           []string `json:"city,optional"`           //城市
 		BuyerClass     []string `json:"buyerClass,optional"`     //客户类型(采购单位行业)
-		Industry       []string `json:"industry,optional"`       //行业分类(信息行业)
 		BusinessScope  string   `json:"businessScope,optional"`  //业务范围(关键词 附加词 排除词)
 		BuyerName      string   `json:"buyerName,optional"`      //采购单位名称
 		AppId          string   `header:"appId"`                 //剑鱼10000
 		UserType       string   `path:"userType"`                //用户标签
 		IsCheckFollow  bool     `json:"isCheckFollow,optional"`  //是否查询关注信息(商机管理用户)
 		IsCheckReceive bool     `json:"isCheckReceive,optional"` //是否查询已领取(商机管理用户)
-		UserId         string   `header:"userId"`                //用户id
-		EntId          string   `header:"entId"`                 //企业id
-		EntUserId      string   `header:"entUserId"`             //商机管理企业用户id
-		Customer       []string `json:"customer,optional"`       //历史客户
-		//SortRule       int64    `json:"sortRule"`       //排序规则
-		//PageNum        int64    `json:"pageNum"`        //当前页码
-		//PageSize       int64    `json:"pageSize"`       //每页数据量
+		UserId         string   `header:"userId,optional"`       //用户id
+		EntId          string   `header:"entId,optional"`        //企业id
+		EntUserId      string   `header:"entUserId,optional"`    //商机管理企业用户id
+		PageSource     string   `json:"pageSource"`              // 来源   search-搜索  index-首页
+		IsContact      int64    `json:"isContact,optional"`      // 是否有联系人 0 不筛选 1-有联系人 2-无联系人
+		PageNum        int64    `json:"pageNum"`                 //当前页码
+		PageSize       int64    `json:"pageSize"`                //每页数据量
 	}
 	//
 	commonResp {

+ 1 - 4
jyBXBuyer/api/internal/logic/buyerSearchListLogic.go

@@ -39,8 +39,6 @@ func (l *BuyerSearchListLogic) BuyerSearchList(req *types.BuyerListReq) (resp *t
 		BuyerName:      req.BuyerName,
 		Province:       req.Province,
 		City:           req.City,
-		BusinessScope:  req.BusinessScope,
-		Industry:       req.Industry,
 		BuyerClass:     req.BuyerClass,
 		IsCheckFollow:  req.IsCheckFollow,
 		IsCheckReceive: req.IsCheckReceive,
@@ -48,7 +46,6 @@ func (l *BuyerSearchListLogic) BuyerSearchList(req *types.BuyerListReq) (resp *t
 		UserId:         l.r.Header.Get("userId"),
 		EntId:          req.EntId,
 		EntUserId:      req.EntUserId,
-		Customer:       req.Customer,
 	})
 	if err0 != nil {
 		return &types.CommonResp{
@@ -62,5 +59,5 @@ func (l *BuyerSearchListLogic) BuyerSearchList(req *types.BuyerListReq) (resp *t
 		Err_msg:  res.ErrMsg,
 		Data:     res.Data,
 	}, nil
-	return
+
 }

+ 7 - 5
jyBXBuyer/api/internal/types/types.go

@@ -5,17 +5,19 @@ type BuyerListReq struct {
 	Province       []string `json:"province,optional"`       //省份
 	City           []string `json:"city,optional"`           //城市
 	BuyerClass     []string `json:"buyerClass,optional"`     //客户类型(采购单位行业)
-	Industry       []string `json:"industry,optional"`       //行业分类(信息行业)
 	BusinessScope  string   `json:"businessScope,optional"`  //业务范围(关键词 附加词 排除词)
 	BuyerName      string   `json:"buyerName,optional"`      //采购单位名称
 	AppId          string   `header:"appId"`                 //剑鱼10000
 	UserType       string   `path:"userType"`                //用户标签
 	IsCheckFollow  bool     `json:"isCheckFollow,optional"`  //是否查询关注信息(商机管理用户)
 	IsCheckReceive bool     `json:"isCheckReceive,optional"` //是否查询已领取(商机管理用户)
-	UserId         string   `header:"userId"`                //用户id
-	EntId          string   `header:"entId"`                 //企业id
-	EntUserId      string   `header:"entUserId"`             //商机管理企业用户id
-	Customer       []string `json:"customer,optional"`       //历史客户
+	UserId         string   `header:"userId,optional"`       //用户id
+	EntId          string   `header:"entId,optional"`        //企业id
+	EntUserId      string   `header:"entUserId,optional"`    //商机管理企业用户id
+	PageSource     string   `json:"pageSource"`              // 来源   search-搜索  index-首页
+	IsContact      int64    `json:"isContact,optional"`      // 是否有联系人 0 不筛选 1-有联系人 2-无联系人
+	PageNum        int64    `json:"pageNum"`                 //当前页码
+	PageSize       int64    `json:"pageSize"`                //每页数据量
 }
 
 type CommonResp struct {

+ 22 - 20
jyBXBuyer/rpc/bxbuyer.proto

@@ -1,7 +1,7 @@
 syntax = "proto3";
 
 package bxbuyer;
-option go_package="./bxbuyer";
+option go_package = "./bxbuyer";
 
 message BuyerListReq {
   string appId = 1;//剑鱼默认10000
@@ -10,18 +10,17 @@ message BuyerListReq {
   string  buyerName = 4;//采购单位名称
   repeated string  province = 5;//省份
   repeated string  city = 6;//城市
-  string  businessScope = 7;//关键词 附加词 排除词
-  int64  sortRule = 8;//排序规则
-  bool  isCheckFollow = 9;//是否查询关注信息(商机管理用户)
-  bool  isCheckReceive = 10;//是否查询已领取(商机管理用户)
-  repeated string  industry = 11;//行业
-  repeated string  buyerClass = 12;//采购单位类型
-  string  userId = 13;
-  string  userType = 14;//用户状态 fType:免费用户	pType:付费用户	vType:超级订阅用户	mType:大会员用户	eType:商机管理用户
-  string  platform = 15;//请求平台
-  string entId = 16;//企业id
-  string entUserId = 17;//商机管理用户id
-  repeated string  customer = 18;//历史客户
+  int64  sortRule = 7;//排序规则
+  bool  isCheckFollow = 8;//是否查询关注信息(商机管理用户)
+  bool  isCheckReceive = 9;//是否查询已领取(商机管理用户)
+  repeated string  buyerClass = 10;//采购单位类型
+  string  userId = 11;
+  string  userType = 12;//用户状态 fType:免费用户	pType:付费用户	vType:超级订阅用户	mType:大会员用户	eType:商机管理用户
+  string  platform = 13;//请求平台
+  string entId = 14;//企业id
+  string entUserId = 15;//商机管理用户id
+  string pageSource = 16;// 来源   search-搜索  index-首页
+  int64  isContact = 17;// 是否有联系人:0-全部; 1-有 ;2-无
 }
 
 message BuyerListResp {
@@ -36,13 +35,16 @@ message BuyerData {
 
 message  BuyerList {
   string  buyer = 1;//采购单位名称
-  double  budget = 2;//预算
-  string  province = 3;//省份
-  string  city = 4;//城市
-  int64  pCount = 5;//项目数量
-  bool  isFollowed = 6;//是否关注
-  bool  isReceived = 7;//是否已领取
-  string  recId = 8;//领取id
+  string  province = 2;//省份
+  string  city = 3;//城市
+  bool  isFollowed = 4;//是否关注
+  bool  isReceived = 5;//是否已领取
+  string  recId = 6;//领取id
+  string buyerClass = 7;// 采购单位类型
+  int64 biddingCount = 8;// 招标动态数量
+  int64 contactCount = 9;// 历史联系人数量
+  int64 projectCount = 10;// 采购项目数量
+  float bidAmountCount = 11;// 采购规模
 }
 
 service Bxbuyer {

+ 23 - 22
jyBXBuyer/rpc/etc/bxbuyer.yaml

@@ -2,30 +2,31 @@ Name: bxbuyer.rpc
 ListenOn: 127.0.0.1:8008
 Etcd:
   Hosts:
-  - 127.0.0.1:2379
+    - 127.0.0.1:2379
   Key: bxbuyer.rpc
 Timeout: 8000
 Webrpcport: 8018
 BuyerCount: 500
 DefaultBuyerNames:
-    - "吉林省农村信用社联合社"
-    - "包头职业技术学院"
-    - "中国民生银行股份有限公司"
-    - "广东烟草梅州市有限公司"
-    - "宁波市自然资源和规划局"
-    - "正数网络技术有限公司"
-    - "浙江创联信息技术股份有限公司"
-    - "甘肃省农村信用社联合社"
-    - "广西壮族自治区自然资源厅"
-    - "华数传媒网络有限公司"
-    - "无锡地铁集团有限公司"
-    - "天津银行股份有限公司"
-    - "广州信息投资有限公司"
-    - "国联证券股份有限公司"
-    - "北京航空航天大学宁波创新研究院"
-    - "湖北省卫生健康委员会"
-    - "上海浦东发展银行股份有限公司信用卡中心"
-    - "上海市房屋管理局"
-    - "长三角金融科技有限公司"
-    - "华能信息技术有限公司"
-    - "浙江华数广电网络股份有限公司"
+  - "吉林省农村信用社联合社"
+  - "包头职业技术学院"
+  - "中国民生银行股份有限公司"
+  - "广东烟草梅州市有限公司"
+  - "宁波市自然资源和规划局"
+  - "正数网络技术有限公司"
+  - "浙江创联信息技术股份有限公司"
+  - "甘肃省农村信用社联合社"
+  - "广西壮族自治区自然资源厅"
+  - "华数传媒网络有限公司"
+  - "无锡地铁集团有限公司"
+  - "天津银行股份有限公司"
+  - "广州信息投资有限公司"
+  - "国联证券股份有限公司"
+  - "北京航空航天大学宁波创新研究院"
+  - "湖北省卫生健康委员会"
+  - "上海浦东发展银行股份有限公司信用卡中心"
+  - "上海市房屋管理局"
+  - "长三角金融科技有限公司"
+  - "华能信息技术有限公司"
+  - "浙江华数广电网络股份有限公司"
+BuyerSearchLimit: 100  # 采购单位搜索数量限制

+ 1 - 0
jyBXBuyer/rpc/internal/config/config.go

@@ -10,6 +10,7 @@ type Config struct {
 	Webrpcport        int64
 	BuyerCount        int64
 	DefaultBuyerNames []string
+	BuyerSearchLimit  int64
 }
 
 type Db struct {

+ 14 - 10
jyBXBuyer/rpc/internal/logic/buyerlistlogic.go

@@ -5,6 +5,7 @@ import (
 	"context"
 	"encoding/json"
 	"github.com/zeromicro/go-zero/core/logx"
+	IC "jyBXBuyer/rpc/init"
 	"jyBXBuyer/rpc/internal/svc"
 	"jyBXBuyer/rpc/model"
 	"jyBXBuyer/rpc/type/bxbuyer"
@@ -27,8 +28,9 @@ func NewBuyerListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *BuyerLi
 // 采购单位搜索
 func (l *BuyerListLogic) BuyerList(in *bxbuyer.BuyerListReq) (*bxbuyer.BuyerListResp, error) {
 	logx.Info("----:", model.CheckEmpty(in))
-	query := ""
+	query, CountQuery := "", ""
 	resp := &bxbuyer.BuyerListResp{}
+	// 采购单位搜索过来的 最多查100条
 	if model.CheckEmpty(in) {
 		//获取缓存数据
 		var isBool = true
@@ -41,8 +43,8 @@ func (l *BuyerListLogic) BuyerList(in *bxbuyer.BuyerListReq) (*bxbuyer.BuyerList
 			}
 		}
 		if isBool {
-			query = model.BuyerListRedisCacheQuery()
-			resp = model.GetBuyerList(query, in, true)
+			query, CountQuery = model.BuyerListRedisCacheQuery()
+			resp = model.GetBuyerList(query, CountQuery, in, true)
 			b, err := json.Marshal(resp.Data)
 			if err == nil {
 				redis.PutBytes("other", model.P_redis_key, &b, model.P_redis_time)
@@ -51,13 +53,15 @@ func (l *BuyerListLogic) BuyerList(in *bxbuyer.BuyerListReq) (*bxbuyer.BuyerList
 			}
 		}
 	} else {
-		query = model.BuyerListQuery(in)
+		query, CountQuery = model.BuyerListQuery(in)
 		logx.Info("query:", query)
-		resp = model.GetBuyerList(query, in, false)
+		resp = model.GetBuyerList(query, CountQuery, in, false) // 查询数据
+		//todo 补充招标动态数量 、历史联系人数量、采购项目数量、采购规模数量
+		resp = model.SupplyBuyerListData(resp)
+		if resp.Data.Count > IC.C.BuyerSearchLimit {
+			resp.Data.Count = IC.C.BuyerSearchLimit
+		}
 	}
-	return &bxbuyer.BuyerListResp{
-		Data:    resp.Data,
-		ErrMsg:  resp.ErrMsg,
-		ErrCode: resp.ErrCode,
-	}, nil
+
+	return resp, nil
 }

+ 258 - 151
jyBXBuyer/rpc/model/buyerListBYEs.go

@@ -16,21 +16,21 @@ import (
 	"github.com/zeromicro/go-zero/core/logx"
 )
 
+const (
+	HasContact = 1 // 采购单位是否有联系方式筛选项 1-有联系方式
+	NoContact  = 2 //  无联系方式
+)
+
 type BScope struct {
 	Keyword         []string `json:"keyword"`
 	AdditionalWords []string `json:"additionalWords"`
 	ExcludedWords   []string `json:"excludedWords"`
 }
 
-//获取采购单位查询query
-func BuyerListQuery(in *bxbuyer.BuyerListReq) (qstr string) {
-	query_bool_must_and := `{"bool": {"must": [%s]%s}}`
-	multi_match := `{"multi_match": {"query": %s,"type": "phrase", "fields": [%s]}}`
-	query := `{"size": 0,"query":{"bool":{"must":[%s],"must_not": [{"term": {"buyer": ""}}],"should":[%s],"minimum_should_match": %d}},%s}`
+// 获取采购单位查询query
+func BuyerListQuery(in *bxbuyer.BuyerListReq) (qstr string, CountQstr string) {
+	query := `{%s "query":{"bool":{"must":[%s],"must_not": [{"term": {"buyer_name": ""}}],"should":[%s],"minimum_should_match": %d}}}`
 	//21.1.20  为和画像保持一致  数据组要求 budget 改成 bidamount
-	query_aggs := `"aggs": {"group_field": {"terms": {"field": %s,"size": %d%s},"aggs": {"count": {"sum": {"field": "bidamount"}}}}}`
-	query_sort := `,"order": {"count": "desc"}`
-	query_bool_must := `{"terms":{"%s":[%s]}}`
 	query_bool_should := `{"bool":{"should":[%s],"minimum_should_match": 1}}`
 
 	bools := []string{}
@@ -38,7 +38,7 @@ func BuyerListQuery(in *bxbuyer.BuyerListReq) (qstr string) {
 	musts_should := []string{}
 	//省份
 	if len(in.Province) > 0 {
-		musts_should = append(musts_should, fmt.Sprintf(`{"terms":{"area":["%s"]}}`, strings.Join(in.Province, "\",\"")))
+		musts_should = append(musts_should, fmt.Sprintf(`{"terms":{"province":["%s"]}}`, strings.Join(in.Province, "\",\"")))
 	}
 	//城市
 	if len(in.City) > 0 {
@@ -49,7 +49,7 @@ func BuyerListQuery(in *bxbuyer.BuyerListReq) (qstr string) {
 	}
 	//采购单位名称
 	if len(in.BuyerName) > 0 {
-		entNameQuery := `{"match_phrase":{"buyer.mbuyer":"` + in.BuyerName + `"}}`
+		entNameQuery := `{"match_phrase":{"name":"` + in.BuyerName + `"}}`
 		musts = append(musts, entNameQuery)
 	}
 	//采购单位类型
@@ -65,96 +65,155 @@ func BuyerListQuery(in *bxbuyer.BuyerListReq) (qstr string) {
 		Buyerclass += `]}}`
 		musts = append(musts, Buyerclass)
 	}
-	//行业
-	industry := in.Industry
-	if len(industry) > 0 {
-		musts = append(musts, fmt.Sprintf(query_bool_must, "subscopeclass", `"`+strings.Join(industry, `","`)+`"`))
-	}
-	if len(in.Customer) > 0 {
-		entcustomerClass := `{"terms":{"buyer":[`
-		for k, v := range in.Customer {
-			if k > 0 {
-				entcustomerClass += `,`
-			}
-			entcustomerClass += `"` + v + `"`
-		}
-		entcustomerClass += `]}}`
-		musts = append(musts, entcustomerClass)
+	// 采购单位联系方式  0-不限 1-有联系人 2-无联系人
+	if in.IsContact != 0 {
+		isContact := MC.If(in.IsContact == int64(HasContact), true, false)
+		isContactStr := `{"term":{"is_contact":` + fmt.Sprint(isContact) + `}}`
+		musts = append(musts, isContactStr)
 	}
-	//业务范围
 	boolsNum := 0
-	if in.BusinessScope != "" {
-		var BScopes = []BScope{}
-		json.Unmarshal([]byte(in.BusinessScope), &BScopes)
-		boolsNum = 1
-		findfields := `"projectname.pname","purchasing"`
-		multi_match = fmt.Sprintf(multi_match, "%s", findfields)
-		for _, v := range BScopes {
-			shoulds := []string{}
-			must_not := []string{}
-			//关键词
-			if len(v.Keyword) > 0 {
-				for _, kv := range v.Keyword {
-					shoulds = append(shoulds, fmt.Sprintf(multi_match, "\""+kv+"\""))
-				}
-			}
-			//附加词
-			if len(v.AdditionalWords) > 0 {
-				for _, av := range v.AdditionalWords {
-					shoulds = append(shoulds, fmt.Sprintf(multi_match, "\""+av+"\""))
-				}
-			}
-			if len(v.ExcludedWords) > 0 {
-				//排除词
-				for _, ev := range v.ExcludedWords {
-					must_not = append(must_not, fmt.Sprintf(multi_match, "\""+ev+"\""))
-				}
-			}
-			//添加
-			if len(shoulds) > 0 {
-				notStr := ""
-				if len(must_not) > 0 {
-					notStr = fmt.Sprintf(`,"must_not":[%s]`, strings.Join(must_not, ","))
-				}
-				bools = append(bools, fmt.Sprintf(query_bool_must_and, strings.Join(shoulds, ","), notStr))
-			}
-		}
-	}
-	query_aggs = fmt.Sprintf(query_aggs, `"buyer"`, IC.C.BuyerCount, "%s")
-	if in.SortRule == 0 { //项目总数排序
-		query_sort = ""
-	}
-	query_aggs = fmt.Sprintf(query_aggs, query_sort)
-	qstr = fmt.Sprintf(query, strings.Join(musts, ","), strings.Join(bools, ","), boolsNum, query_aggs)
+	qstr = fmt.Sprintf(query, fmt.Sprintf(`"from":%d,"size": %d,`, (in.PageNum-1)*in.PageSize, in.PageSize), strings.Join(musts, ","), strings.Join(bools, ","), boolsNum)
+	CountQstr = fmt.Sprintf(query, "", strings.Join(musts, ","), strings.Join(bools, ","), boolsNum)
 	return
 }
 
+// 采购单位补充采购规模、项目数量、招标动态数量
+func SupplyDataQuery(buyerList []string) (query string) {
+	// 查近两年的数据   因为bigmember  BuyerMiniPortrait 查的默认是两年
+	q := `{"size":0,"query": { "bool": { "must": [ {"terms": { "buyer": ["` + strings.Join(buyerList, "\",\"") + `"] }},{"range": {"jgtime": {"gte": %d,"lt": %d} }} ]}}, "aggs": { "buyerBuckets": {"terms": {"field": "buyer"
+ },"aggs": {"bidAmountCount": {"sum": {"field": "bidamount"}}}}}}`
+	start, end := getTimeRage()
+	return fmt.Sprintf(q, start.Unix(), end.Unix())
+}
+func getTimeRage() (st, et time.Time) {
+	now := time.Now()
+	eYear := now.Year()
+	sYear := now.Year() - 2
+	//返回默认时间
+	sTimeStamp := time.Date(sYear, 1, 1, 0, 0, 0, 0, time.Local)
+	eTimeStamp := time.Date(eYear, now.Month(), now.Day(), now.Hour(), now.Minute(), 0, 0, time.Local)
+
+	return sTimeStamp, eTimeStamp
+
+}
+
 const (
 	P_INDEX      = "projectset"
 	P_TYPE       = "projectset"
 	P_redis_time = 15 * 24 * 60 * 60 //redis存15天
 	P_redis_key  = "buyerListCache"
+	BuyerIndex   = "buyer_v2" // 采购单位index
+	BuyerType    = "_doc"
+	biddingIndex = "bidding"
+	biddingType  = "bidding"
 )
 
-//查询采购单位列表
-func GetBuyerList(qstr string, in *bxbuyer.BuyerListReq, isCache bool) (resp *bxbuyer.BuyerListResp) {
+// 查询采购单位列表
+func GetBuyerList(qstr string, CountQuery string, in *bxbuyer.BuyerListReq, isCache bool) (resp *bxbuyer.BuyerListResp) {
 	t1 := time.Now()
-	aggs := GetAggs(P_INDEX, P_TYPE, qstr)
+	total := elastic.Count(BuyerIndex, BuyerType, CountQuery) // 总数
 	resp = &bxbuyer.BuyerListResp{
-		Data: &bxbuyer.BuyerData{},
+		Data: &bxbuyer.BuyerData{
+			Count: total,
+			List:  []*bxbuyer.BuyerList{},
+		},
+	}
+	if total == 0 {
+		return
+	}
+	rs := elastic.Get(BuyerIndex, BuyerType, qstr) // 采购单位列表
+	if rs == nil || len(*rs) == 0 {
+		return
+	}
+	for i := 0; i < len(*rs); i++ {
+		tmp := &bxbuyer.BuyerList{
+			Buyer:      MC.ObjToString((*rs)[i]["buyer_name"]),
+			Province:   MC.ObjToString((*rs)[i]["province"]),
+			City:       MC.ObjToString((*rs)[i]["city"]),
+			BuyerClass: MC.ObjToString((*rs)[i]["buyerclasss"]),
+		}
+		resp.Data.List = append(resp.Data.List, tmp)
+
+	}
+	var wg sync.WaitGroup
+	//省份和城市 是否查询已关注信息 是否查询已领取信息
+	//企业信用库qyxy_std 和es buyer库 查询省份和城市
+	var fiftyArr = []*bxbuyer.BuyerList{}
+	var buyerNames = []string{}
+	for bk, bv := range resp.Data.List {
+		fiftyArr = append(fiftyArr, bv)
+		buyerNames = append(buyerNames, bv.Buyer)
+		if (bk+1)%50 == 0 || len(resp.Data.List) == bk+1 {
+			wg.Add(1)
+			go func(wg *sync.WaitGroup, fiftyArr []*bxbuyer.BuyerList, buyerNames []string, icf, icr bool, userId, entUserId string) {
+				// 关注状态 领取状态
+				//关注状态
+				isFws := map[string]bool{}
+				if icf {
+					isFws = IsFollowd(buyerNames, userId)
+				}
+				//领取状态
+				isRws := map[string]string{}
+				if icr {
+					isRws = IsReceived(buyerNames, entUserId)
+				}
+				//log.Println("---:", isRws)
+				for _, fv := range fiftyArr {
+					if icf {
+						fv.IsFollowed = isFws[fv.Buyer]
+					}
+					if icr {
+						if isRws[fv.Buyer] != "" {
+							fv.RecId = isRws[fv.Buyer]
+							fv.IsReceived = true
+						}
+					}
+				}
+				wg.Done()
+			}(&wg, fiftyArr, buyerNames, in.IsCheckFollow, in.IsCheckReceive, in.UserId, in.EntUserId)
+			fiftyArr = []*bxbuyer.BuyerList{}
+			buyerNames = []string{}
+		}
+	}
+	wg.Wait()
+
+	logx.Info("耗时;", time.Since(t1).Seconds(), time.Since(t1).Microseconds())
+	return
+}
+
+// 补充字段   项目数量 历史联系人数量 采购单位规模
+func SupplyBuyerListData(resp *bxbuyer.BuyerListResp) *bxbuyer.BuyerListResp {
+	if resp == nil || resp.Data == nil || resp.Data.List == nil || len(resp.Data.List) == 0 {
+		return resp
+	}
+	// buyerList
+	buyerList := []string{}
+	for i := 0; i < len(resp.Data.List); i++ {
+		buyerList = append(buyerList, resp.Data.List[i].Buyer)
 	}
-	type GroupStruct struct {
+	query := SupplyDataQuery(buyerList) // 招标动态数量、项目数量、采购规模
+	// 聚合查
+	aggs := GetAggs(P_INDEX, P_TYPE, query)
+
+	type BuyerAggStruct struct {
 		Buckets []struct {
-			Key       string `json:"key,omitempty"`
-			Doc_count int64  `json:"doc_count,omitempty"`
-			Count     struct {
-				Value float64 `json:"value,omitempty"`
-			} `json:"count"`
+			Key            string `json:"key,omitempty"`
+			Doc_count      int64  `json:"doc_count,omitempty"`
+			BidAmountCount struct {
+				Value float32 `json:"value,omitempty"`
+			} `json:"bidAmountCount"`
 		} `json:"buckets"`
 	}
-	var group = GroupStruct{}
-	if aggs != nil && aggs["group_field"] != nil {
-		bs, err := aggs["group_field"].MarshalJSON()
+	var buyerBuckets = BuyerAggStruct{}
+	type supplyDataStruct struct {
+		ProjectCount   int64
+		BidCount       int64
+		BidAmountCount float32
+	}
+	// 处理成map 用于后面格式化数据
+	buyerMap := map[string]supplyDataStruct{}
+	if aggs != nil && aggs["buyerBuckets"] != nil {
+		bs, err := aggs["buyerBuckets"].MarshalJSON()
 		if err != nil {
 			resp.ErrCode = -1
 			resp.ErrMsg = "获取数据异常"
@@ -162,72 +221,124 @@ func GetBuyerList(qstr string, in *bxbuyer.BuyerListReq, isCache bool) (resp *bx
 			if len(bs) == 0 {
 				resp.ErrMsg = "暂无数据"
 			} else {
-				json.Unmarshal(bs, &group)
-				if len(group.Buckets) > 0 {
-					for _, v := range group.Buckets {
-						var list = &bxbuyer.BuyerList{}
-						list.Buyer = v.Key
-						list.Budget = v.Count.Value
-						list.PCount = v.Doc_count
-						resp.Data.List = append(resp.Data.List, list)
+				json.Unmarshal(bs, &buyerBuckets)
+				if len(buyerBuckets.Buckets) > 0 {
+					for _, v := range buyerBuckets.Buckets {
+						buyerMap[v.Key] = supplyDataStruct{
+							BidAmountCount: v.BidAmountCount.Value,
+							ProjectCount:   v.Doc_count,
+						}
 					}
 				}
 			}
 		}
 	}
-	resp.Data.Count = int64(len(resp.Data.List))
-	logx.Info("=---count---===", resp.Data.Count)
-	if len(resp.Data.List) > 0 {
-		var wg sync.WaitGroup
-		//省份和城市 是否查询已关注信息 是否查询已领取信息
-		//企业信用库qyxy_std 和es buyer库 查询省份和城市
-		var fiftyArr = []*bxbuyer.BuyerList{}
-		var buyerNames = []string{}
-		for bk, bv := range resp.Data.List {
-			fiftyArr = append(fiftyArr, bv)
-			buyerNames = append(buyerNames, bv.Buyer)
-			if (bk+1)%50 == 0 || len(resp.Data.List) == bk+1 {
-				wg.Add(1)
-				go func(wg *sync.WaitGroup, fiftyArr []*bxbuyer.BuyerList, buyerNames []string, icf, icr bool, userId, entUserId string) {
-					//省份城市 关注状态 领取状态
-					infoMap := GetBuyerInfo(buyerNames)
-					//关注状态
-					isFws := map[string]bool{}
-					if icf {
-						isFws = IsFollowd(buyerNames, userId)
-					}
-					//领取状态
-					isRws := map[string]string{}
-					if icr {
-						isRws = IsReceived(buyerNames, entUserId)
-					}
-					//log.Println("---:", isRws)
-					for _, fv := range fiftyArr {
-						fv.Province = infoMap[fv.Buyer].Province
-						fv.City = infoMap[fv.Buyer].City
-						if icf {
-							fv.IsFollowed = isFws[fv.Buyer]
-						}
-						if icr {
-							if isRws[fv.Buyer] != "" {
-								fv.RecId = isRws[fv.Buyer]
-								fv.IsReceived = true
-							}
-						}
-					}
-					wg.Done()
-				}(&wg, fiftyArr, buyerNames, in.IsCheckFollow, in.IsCheckReceive, in.UserId, in.EntUserId)
-				fiftyArr = []*bxbuyer.BuyerList{}
-				buyerNames = []string{}
+	ch := make(chan int, 10)
+	ch2 := make(chan int, 10)
+	wg := &sync.WaitGroup{}
+	for i := 0; i < len(resp.Data.List); i++ {
+		buyer := resp.Data.List[i].Buyer
+		// 补充字段
+		if supplyData, ok := buyerMap[buyer]; ok {
+			resp.Data.List[i].BidAmountCount = supplyData.BidAmountCount
+			resp.Data.List[i].ProjectCount = supplyData.ProjectCount
+		}
+		ch <- 1
+		wg.Add(1)
+		go func(list *bxbuyer.BuyerList, buyer string) {
+			defer func() {
+				<-ch
+				wg.Done()
+			}()
+			list.BiddingCount = GetNewBiddingCount(buyer)
+		}(resp.Data.List[i], buyer)
+		ch2 <- 1
+		wg.Add(1)
+		go func(list *bxbuyer.BuyerList, buyer string) {
+			defer func() {
+				<-ch2
+				wg.Done()
+			}()
+			list.ContactCount = GetProjectContactCount(buyer) // 补充联系人字段
+		}(resp.Data.List[i], buyer)
+
+	}
+	wg.Wait()
+	return resp
+}
+
+func GetProjectContactCount(buyerName string) int64 {
+	list := []string{}
+	var musts []string
+	if buyerName != "" {
+		musts = append(musts, fmt.Sprintf(`{"term":{"buyer":"%s"}}`, buyerName))
+	}
+	if musts == nil || len(musts) == 0 {
+		return 0
+	}
+	searchSql := fmt.Sprintf(`{"query":{"bool":{"must":[%s]}},"_source":["_id","zbtime","projectname","list"],"sort":[{"zbtime":"desc"}],"size":500}`, strings.Join(musts, ","))
+	projectList := elastic.Get("projectset", "projectset", searchSql)
+	if projectList == nil || len(*projectList) == 0 {
+		return 0
+	}
+	//根据联系人和联系方式展示
+	//多个项目同一个联系人;只展示最新项目
+	//一个项目多个联系人;拆分展示
+	repeatContacts := map[string]bool{}
+	for _, rowData := range *projectList {
+		mapList, ok := rowData["list"].([]interface{})
+		if !ok || len(mapList) == 0 {
+			continue
+		}
+		for i := len(mapList) - 1; i >= 0; i-- {
+			thisMsg, ok := mapList[i].(map[string]interface{})
+			if !ok || len(thisMsg) == 0 {
+				continue
+			}
+			thisPhone, thisPerson := "", ""
+			if buyerName != "" {
+				if thisPhone, _ = thisMsg["buyertel"].(string); thisPhone != "" {
+					thisPerson, _ = thisMsg["buyerperson"].(string)
+				}
+			}
+			if thisPhone == "" { //联系人为空则不展示 dev4.7.3联系人为空展示此记录
+				continue
+			}
+			//一个项目只选取一条公告联系人
+			thisAddPerson := false
+			//名字中多个联系人拆分
+			for _, name := range strings.Split(thisPerson, ",") {
+				thisName := strings.TrimSpace(name)
+				if thisName == "" && thisAddPerson { //联系人为空则不展示
+					continue
+				}
+				thisAddPerson = true
+				repeatKey := fmt.Sprintf("%s_%s", thisName, thisPhone)
+				if repeatContacts[repeatKey] {
+					continue
+				}
+				repeatContacts[repeatKey] = true
+				list = append(list, thisPhone)
+			}
+			if thisAddPerson {
+				break
 			}
 		}
-		wg.Wait()
 	}
-	logx.Info("耗时;", time.Since(t1).Seconds(), time.Since(t1).Microseconds())
-	return
+	return int64(len(list))
+}
+func GetNewBiddingCount(buyer string) int64 {
+	if buyer == "" {
+		return 0
+	}
+	var mustQuery []string
+	st, et := getTimeRage()
+	mustQuery = append(mustQuery, fmt.Sprintf(`{"range":{"publishtime":{"gte":%d,"lte":%d}}}`, st.Unix(), et.Unix()))
+	mustQuery = append(mustQuery, fmt.Sprintf(`{"term": {"buyer": "%s"}}`, buyer))
+	return elastic.Count(biddingIndex, biddingType, fmt.Sprintf(`{"query":{"bool":{"must":[%s]}}}`, strings.Join(mustQuery, ",")))
 }
 
-//聚合查询
+// 聚合查询
 func GetAggs(index, itype, query string) (aggs map[string]json.RawMessage) {
 	aggs, _, _ = elastic.GetAggs(index, itype, query)
 	return
@@ -238,7 +349,7 @@ type buyerInfo struct {
 	City     string
 }
 
-//潜在客户 获取省份和城市
+// 潜在客户 获取省份和城市
 func GetBuyerInfo(buyerNames []string) (infoMap map[string]buyerInfo) {
 	var buyerInfoQuery = `{"query": {"bool": {"must": [{"terms": {"%s": [%s]}}],"must_not": [],"should": []}},"from": 0,"size": 50,"sort": []}`
 	query := fmt.Sprintf(buyerInfoQuery, "buyer_name", `"`+strings.Join(buyerNames, `","`)+`"`)
@@ -260,7 +371,7 @@ func GetBuyerInfo(buyerNames []string) (infoMap map[string]buyerInfo) {
 }
 
 var fc = "follow_customer" //关注客户表
-//采购单位是否作为客户已被关注
+// 采购单位是否作为客户已被关注
 func IsFollowd(buyerNames []string, userId string) (isFws map[string]bool) {
 	queryMap := map[string]interface{}{
 		"userId": userId,
@@ -289,7 +400,7 @@ var (
 	Entniche_user_customer = "entniche_user_customer"
 )
 
-//领取状态
+// 领取状态
 func IsReceived(buyerNames []string, entUserId string) (isRws map[string]string) {
 	//新加领取的客户id----保证领取的唯一性
 	receInfos := IC.MainMysql.SelectBySql(fmt.Sprintf("SELECT ecn.id,  ecn.name  FROM %s ecn,%s  euu WHERE ecn.id = euu.customer_id AND euu.user_id =? AND ecn.`name` IN  ('%s') AND (euu.source_type =1 or euu.source_type=4)", Entniche_customer, Entniche_user_customer, strings.Join(buyerNames, "','")), entUserId)
@@ -308,9 +419,9 @@ func IsReceived(buyerNames []string, entUserId string) (isRws map[string]string)
 	return
 }
 
-//是否为空请求
+// 是否为空请求
 func CheckEmpty(in *bxbuyer.BuyerListReq) bool {
-	if in.BuyerName == "" && len(in.BuyerClass) == 0 && len(in.Province) == 0 && len(in.City) == 0 && len(in.Industry) == 0 && in.BusinessScope == "" && len(in.Customer) == 0 {
+	if in.BuyerName == "" && len(in.BuyerClass) == 0 && len(in.Province) == 0 && len(in.City) == 0 {
 		return true
 	}
 	return false
@@ -318,12 +429,10 @@ func CheckEmpty(in *bxbuyer.BuyerListReq) bool {
 
 //缓存数据查询
 
-//获取采购单位查询query
-func BuyerListRedisCacheQuery() (qstr string) {
-	query := `{"size": 0,"query":{"bool":{"must":[%s],"must_not": [{"term": {"buyer": ""}}],"should":[],"minimum_should_match": %d}},%s}`
+// 获取采购单位查询query
+func BuyerListRedisCacheQuery() (qstr string, a string) {
+	query := `{"size": 0,"query":{"bool":{"must":[%s],"must_not": [{"term": {"buyer": ""}}],"should":[],"minimum_should_match": %d}}}`
 	//21.1.20  为和画像保持一致  数据组要求 budget 改成 bidamount
-	query_aggs := `"aggs": {"group_field": {"terms": {"field": %s,"size": %d%s},"aggs": {"count": {"sum": {"field": "bidamount"}}}}}`
-	query_sort := `,"order": {"count": "desc"}`
 	musts := []string{}
 	boolsNum := 0
 	entcustomerClass := `{"terms":{"buyer":[`
@@ -335,9 +444,7 @@ func BuyerListRedisCacheQuery() (qstr string) {
 	}
 	entcustomerClass += `]}}`
 	musts = append(musts, entcustomerClass)
-	query_aggs = fmt.Sprintf(query_aggs, `"buyer"`, len(IC.C.DefaultBuyerNames), "%s")
-	query_aggs = fmt.Sprintf(query_aggs, query_sort)
-	qstr = fmt.Sprintf(query, strings.Join(musts, ","), boolsNum, query_aggs)
+	qstr = fmt.Sprintf(query, strings.Join(musts, ","), boolsNum)
 	logx.Info("qstr:", qstr)
 	return
 }

+ 123 - 105
jyBXBuyer/rpc/type/bxbuyer/bxbuyer.pb.go

@@ -1,13 +1,12 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
-// 	protoc-gen-go v1.23.0
-// 	protoc        v3.15.5
+// 	protoc-gen-go v1.28.0
+// 	protoc        v3.19.4
 // source: bxbuyer.proto
 
 package bxbuyer
 
 import (
-	proto "github.com/golang/protobuf/proto"
 	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
 	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
 	reflect "reflect"
@@ -21,33 +20,28 @@ const (
 	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
 )
 
-// This is a compile-time assertion that a sufficiently up-to-date version
-// of the legacy proto package is being used.
-const _ = proto.ProtoPackageIsVersion4
-
 type BuyerListReq struct {
 	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
 	unknownFields protoimpl.UnknownFields
 
-	AppId          string   `protobuf:"bytes,1,opt,name=appId,proto3" json:"appId,omitempty"`                     //剑鱼默认10000
-	PageNum        int64    `protobuf:"varint,2,opt,name=pageNum,proto3" json:"pageNum,omitempty"`                //当前页码
-	PageSize       int64    `protobuf:"varint,3,opt,name=pageSize,proto3" json:"pageSize,omitempty"`              //每页数量
-	BuyerName      string   `protobuf:"bytes,4,opt,name=buyerName,proto3" json:"buyerName,omitempty"`             //采购单位名称
-	Province       []string `protobuf:"bytes,5,rep,name=province,proto3" json:"province,omitempty"`               //省份
-	City           []string `protobuf:"bytes,6,rep,name=city,proto3" json:"city,omitempty"`                       //城市
-	BusinessScope  string   `protobuf:"bytes,7,opt,name=businessScope,proto3" json:"businessScope,omitempty"`     //关键词 附加词 排除词
-	SortRule       int64    `protobuf:"varint,8,opt,name=sortRule,proto3" json:"sortRule,omitempty"`              //排序规则
-	IsCheckFollow  bool     `protobuf:"varint,9,opt,name=isCheckFollow,proto3" json:"isCheckFollow,omitempty"`    //是否查询关注信息(商机管理用户)
-	IsCheckReceive bool     `protobuf:"varint,10,opt,name=isCheckReceive,proto3" json:"isCheckReceive,omitempty"` //是否查询已领取(商机管理用户)
-	Industry       []string `protobuf:"bytes,11,rep,name=industry,proto3" json:"industry,omitempty"`              //行业
-	BuyerClass     []string `protobuf:"bytes,12,rep,name=buyerClass,proto3" json:"buyerClass,omitempty"`          //采购单位类型
-	UserId         string   `protobuf:"bytes,13,opt,name=userId,proto3" json:"userId,omitempty"`
-	UserType       string   `protobuf:"bytes,14,opt,name=userType,proto3" json:"userType,omitempty"`   //用户状态 fType:免费用户	pType:付费用户	vType:超级订阅用户	mType:大会员用户	eType:商机管理用户
-	Platform       string   `protobuf:"bytes,15,opt,name=platform,proto3" json:"platform,omitempty"`   //请求平台
-	EntId          string   `protobuf:"bytes,16,opt,name=entId,proto3" json:"entId,omitempty"`         //企业id
-	EntUserId      string   `protobuf:"bytes,17,opt,name=entUserId,proto3" json:"entUserId,omitempty"` //商机管理用户id
-	Customer       []string `protobuf:"bytes,18,rep,name=customer,proto3" json:"customer,omitempty"`   //历史客户
+	AppId          string   `protobuf:"bytes,1,opt,name=appId,proto3" json:"appId,omitempty"`                    //剑鱼默认10000
+	PageNum        int64    `protobuf:"varint,2,opt,name=pageNum,proto3" json:"pageNum,omitempty"`               //当前页码
+	PageSize       int64    `protobuf:"varint,3,opt,name=pageSize,proto3" json:"pageSize,omitempty"`             //每页数量
+	BuyerName      string   `protobuf:"bytes,4,opt,name=buyerName,proto3" json:"buyerName,omitempty"`            //采购单位名称
+	Province       []string `protobuf:"bytes,5,rep,name=province,proto3" json:"province,omitempty"`              //省份
+	City           []string `protobuf:"bytes,6,rep,name=city,proto3" json:"city,omitempty"`                      //城市
+	SortRule       int64    `protobuf:"varint,7,opt,name=sortRule,proto3" json:"sortRule,omitempty"`             //排序规则
+	IsCheckFollow  bool     `protobuf:"varint,8,opt,name=isCheckFollow,proto3" json:"isCheckFollow,omitempty"`   //是否查询关注信息(商机管理用户)
+	IsCheckReceive bool     `protobuf:"varint,9,opt,name=isCheckReceive,proto3" json:"isCheckReceive,omitempty"` //是否查询已领取(商机管理用户)
+	BuyerClass     []string `protobuf:"bytes,10,rep,name=buyerClass,proto3" json:"buyerClass,omitempty"`         //采购单位类型
+	UserId         string   `protobuf:"bytes,11,opt,name=userId,proto3" json:"userId,omitempty"`
+	UserType       string   `protobuf:"bytes,12,opt,name=userType,proto3" json:"userType,omitempty"`     //用户状态 fType:免费用户	pType:付费用户	vType:超级订阅用户	mType:大会员用户	eType:商机管理用户
+	Platform       string   `protobuf:"bytes,13,opt,name=platform,proto3" json:"platform,omitempty"`     //请求平台
+	EntId          string   `protobuf:"bytes,14,opt,name=entId,proto3" json:"entId,omitempty"`           //企业id
+	EntUserId      string   `protobuf:"bytes,15,opt,name=entUserId,proto3" json:"entUserId,omitempty"`   //商机管理用户id
+	PageSource     string   `protobuf:"bytes,16,opt,name=pageSource,proto3" json:"pageSource,omitempty"` // 来源   search-搜索  index-首页
+	IsContact      int64    `protobuf:"varint,17,opt,name=isContact,proto3" json:"isContact,omitempty"`  // 是否有联系人:0-全部; 1-有 ;2-无
 }
 
 func (x *BuyerListReq) Reset() {
@@ -124,13 +118,6 @@ func (x *BuyerListReq) GetCity() []string {
 	return nil
 }
 
-func (x *BuyerListReq) GetBusinessScope() string {
-	if x != nil {
-		return x.BusinessScope
-	}
-	return ""
-}
-
 func (x *BuyerListReq) GetSortRule() int64 {
 	if x != nil {
 		return x.SortRule
@@ -152,13 +139,6 @@ func (x *BuyerListReq) GetIsCheckReceive() bool {
 	return false
 }
 
-func (x *BuyerListReq) GetIndustry() []string {
-	if x != nil {
-		return x.Industry
-	}
-	return nil
-}
-
 func (x *BuyerListReq) GetBuyerClass() []string {
 	if x != nil {
 		return x.BuyerClass
@@ -201,11 +181,18 @@ func (x *BuyerListReq) GetEntUserId() string {
 	return ""
 }
 
-func (x *BuyerListReq) GetCustomer() []string {
+func (x *BuyerListReq) GetPageSource() string {
 	if x != nil {
-		return x.Customer
+		return x.PageSource
 	}
-	return nil
+	return ""
+}
+
+func (x *BuyerListReq) GetIsContact() int64 {
+	if x != nil {
+		return x.IsContact
+	}
+	return 0
 }
 
 type BuyerListResp struct {
@@ -331,14 +318,17 @@ type BuyerList struct {
 	sizeCache     protoimpl.SizeCache
 	unknownFields protoimpl.UnknownFields
 
-	Buyer      string  `protobuf:"bytes,1,opt,name=buyer,proto3" json:"buyer,omitempty"`            //采购单位名称
-	Budget     float64 `protobuf:"fixed64,2,opt,name=budget,proto3" json:"budget,omitempty"`        //预算
-	Province   string  `protobuf:"bytes,3,opt,name=province,proto3" json:"province,omitempty"`      //省份
-	City       string  `protobuf:"bytes,4,opt,name=city,proto3" json:"city,omitempty"`              //城市
-	PCount     int64   `protobuf:"varint,5,opt,name=pCount,proto3" json:"pCount,omitempty"`         //项目数量
-	IsFollowed bool    `protobuf:"varint,6,opt,name=isFollowed,proto3" json:"isFollowed,omitempty"` //是否关注
-	IsReceived bool    `protobuf:"varint,7,opt,name=isReceived,proto3" json:"isReceived,omitempty"` //是否已领取
-	RecId      string  `protobuf:"bytes,8,opt,name=recId,proto3" json:"recId,omitempty"`            //领取id
+	Buyer          string  `protobuf:"bytes,1,opt,name=buyer,proto3" json:"buyer,omitempty"`                      //采购单位名称
+	Province       string  `protobuf:"bytes,2,opt,name=province,proto3" json:"province,omitempty"`                //省份
+	City           string  `protobuf:"bytes,3,opt,name=city,proto3" json:"city,omitempty"`                        //城市
+	IsFollowed     bool    `protobuf:"varint,4,opt,name=isFollowed,proto3" json:"isFollowed,omitempty"`           //是否关注
+	IsReceived     bool    `protobuf:"varint,5,opt,name=isReceived,proto3" json:"isReceived,omitempty"`           //是否已领取
+	RecId          string  `protobuf:"bytes,6,opt,name=recId,proto3" json:"recId,omitempty"`                      //领取id
+	BuyerClass     string  `protobuf:"bytes,7,opt,name=buyerClass,proto3" json:"buyerClass,omitempty"`            // 采购单位类型
+	BiddingCount   int64   `protobuf:"varint,8,opt,name=biddingCount,proto3" json:"biddingCount,omitempty"`       // 招标动态数量
+	ContactCount   int64   `protobuf:"varint,9,opt,name=contactCount,proto3" json:"contactCount,omitempty"`       // 历史联系人数量
+	ProjectCount   int64   `protobuf:"varint,10,opt,name=projectCount,proto3" json:"projectCount,omitempty"`      // 采购项目数量
+	BidAmountCount float32 `protobuf:"fixed32,11,opt,name=bidAmountCount,proto3" json:"bidAmountCount,omitempty"` // 采购规模
 }
 
 func (x *BuyerList) Reset() {
@@ -380,13 +370,6 @@ func (x *BuyerList) GetBuyer() string {
 	return ""
 }
 
-func (x *BuyerList) GetBudget() float64 {
-	if x != nil {
-		return x.Budget
-	}
-	return 0
-}
-
 func (x *BuyerList) GetProvince() string {
 	if x != nil {
 		return x.Province
@@ -401,13 +384,6 @@ func (x *BuyerList) GetCity() string {
 	return ""
 }
 
-func (x *BuyerList) GetPCount() int64 {
-	if x != nil {
-		return x.PCount
-	}
-	return 0
-}
-
 func (x *BuyerList) GetIsFollowed() bool {
 	if x != nil {
 		return x.IsFollowed
@@ -429,11 +405,46 @@ func (x *BuyerList) GetRecId() string {
 	return ""
 }
 
+func (x *BuyerList) GetBuyerClass() string {
+	if x != nil {
+		return x.BuyerClass
+	}
+	return ""
+}
+
+func (x *BuyerList) GetBiddingCount() int64 {
+	if x != nil {
+		return x.BiddingCount
+	}
+	return 0
+}
+
+func (x *BuyerList) GetContactCount() int64 {
+	if x != nil {
+		return x.ContactCount
+	}
+	return 0
+}
+
+func (x *BuyerList) GetProjectCount() int64 {
+	if x != nil {
+		return x.ProjectCount
+	}
+	return 0
+}
+
+func (x *BuyerList) GetBidAmountCount() float32 {
+	if x != nil {
+		return x.BidAmountCount
+	}
+	return 0
+}
+
 var File_bxbuyer_proto protoreflect.FileDescriptor
 
 var file_bxbuyer_proto_rawDesc = []byte{
 	0x0a, 0x0d, 0x62, 0x78, 0x62, 0x75, 0x79, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12,
-	0x07, 0x62, 0x78, 0x62, 0x75, 0x79, 0x65, 0x72, 0x22, 0x94, 0x04, 0x0a, 0x0c, 0x42, 0x75, 0x79,
+	0x07, 0x62, 0x78, 0x62, 0x75, 0x79, 0x65, 0x72, 0x22, 0xf4, 0x03, 0x0a, 0x0c, 0x42, 0x75, 0x79,
 	0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x70, 0x70,
 	0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x61, 0x70, 0x70, 0x49, 0x64, 0x12,
 	0x18, 0x0a, 0x07, 0x70, 0x61, 0x67, 0x65, 0x4e, 0x75, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03,
@@ -444,29 +455,27 @@ var file_bxbuyer_proto_rawDesc = []byte{
 	0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x6e, 0x63, 0x65, 0x18,
 	0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x6e, 0x63, 0x65, 0x12,
 	0x12, 0x0a, 0x04, 0x63, 0x69, 0x74, 0x79, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x63,
-	0x69, 0x74, 0x79, 0x12, 0x24, 0x0a, 0x0d, 0x62, 0x75, 0x73, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x53,
-	0x63, 0x6f, 0x70, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x62, 0x75, 0x73, 0x69,
-	0x6e, 0x65, 0x73, 0x73, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x6f, 0x72,
-	0x74, 0x52, 0x75, 0x6c, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x73, 0x6f, 0x72,
-	0x74, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x24, 0x0a, 0x0d, 0x69, 0x73, 0x43, 0x68, 0x65, 0x63, 0x6b,
-	0x46, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x69, 0x73,
-	0x43, 0x68, 0x65, 0x63, 0x6b, 0x46, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x12, 0x26, 0x0a, 0x0e, 0x69,
-	0x73, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x18, 0x0a, 0x20,
-	0x01, 0x28, 0x08, 0x52, 0x0e, 0x69, 0x73, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x63, 0x65,
-	0x69, 0x76, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x69, 0x6e, 0x64, 0x75, 0x73, 0x74, 0x72, 0x79, 0x18,
-	0x0b, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x69, 0x6e, 0x64, 0x75, 0x73, 0x74, 0x72, 0x79, 0x12,
-	0x1e, 0x0a, 0x0a, 0x62, 0x75, 0x79, 0x65, 0x72, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x18, 0x0c, 0x20,
-	0x03, 0x28, 0x09, 0x52, 0x0a, 0x62, 0x75, 0x79, 0x65, 0x72, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x12,
-	0x16, 0x0a, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52,
-	0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x54,
-	0x79, 0x70, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x54,
-	0x79, 0x70, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x18,
-	0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x12,
-	0x14, 0x0a, 0x05, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05,
-	0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x65, 0x6e, 0x74, 0x55, 0x73, 0x65, 0x72,
-	0x49, 0x64, 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x65, 0x6e, 0x74, 0x55, 0x73, 0x65,
-	0x72, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x65, 0x72, 0x18,
-	0x12, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x65, 0x72, 0x22,
+	0x69, 0x74, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x6f, 0x72, 0x74, 0x52, 0x75, 0x6c, 0x65, 0x18,
+	0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x73, 0x6f, 0x72, 0x74, 0x52, 0x75, 0x6c, 0x65, 0x12,
+	0x24, 0x0a, 0x0d, 0x69, 0x73, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x46, 0x6f, 0x6c, 0x6c, 0x6f, 0x77,
+	0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x69, 0x73, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x46,
+	0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x12, 0x26, 0x0a, 0x0e, 0x69, 0x73, 0x43, 0x68, 0x65, 0x63, 0x6b,
+	0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x69,
+	0x73, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x12, 0x1e, 0x0a,
+	0x0a, 0x62, 0x75, 0x79, 0x65, 0x72, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28,
+	0x09, 0x52, 0x0a, 0x62, 0x75, 0x79, 0x65, 0x72, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x12, 0x16, 0x0a,
+	0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x75,
+	0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x54, 0x79, 0x70,
+	0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x54, 0x79, 0x70,
+	0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x18, 0x0d, 0x20,
+	0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x12, 0x14, 0x0a,
+	0x05, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6e,
+	0x74, 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x65, 0x6e, 0x74, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64,
+	0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x65, 0x6e, 0x74, 0x55, 0x73, 0x65, 0x72, 0x49,
+	0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18,
+	0x10, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x61, 0x67, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63,
+	0x65, 0x12, 0x1c, 0x0a, 0x09, 0x69, 0x73, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x18, 0x11,
+	0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x69, 0x73, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x22,
 	0x6b, 0x0a, 0x0d, 0x42, 0x75, 0x79, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70,
 	0x12, 0x19, 0x0a, 0x08, 0x65, 0x72, 0x72, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01,
 	0x28, 0x03, 0x52, 0x07, 0x65, 0x72, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x65,
@@ -478,26 +487,35 @@ var file_bxbuyer_proto_rawDesc = []byte{
 	0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12,
 	0x26, 0x0a, 0x04, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e,
 	0x62, 0x78, 0x62, 0x75, 0x79, 0x65, 0x72, 0x2e, 0x42, 0x75, 0x79, 0x65, 0x72, 0x4c, 0x69, 0x73,
-	0x74, 0x52, 0x04, 0x6c, 0x69, 0x73, 0x74, 0x22, 0xd7, 0x01, 0x0a, 0x09, 0x42, 0x75, 0x79, 0x65,
+	0x74, 0x52, 0x04, 0x6c, 0x69, 0x73, 0x74, 0x22, 0xdb, 0x02, 0x0a, 0x09, 0x42, 0x75, 0x79, 0x65,
 	0x72, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x75, 0x79, 0x65, 0x72, 0x18, 0x01,
-	0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x62, 0x75, 0x79, 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x62,
-	0x75, 0x64, 0x67, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x06, 0x62, 0x75, 0x64,
-	0x67, 0x65, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x6e, 0x63, 0x65, 0x18,
-	0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x6e, 0x63, 0x65, 0x12,
-	0x12, 0x0a, 0x04, 0x63, 0x69, 0x74, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63,
-	0x69, 0x74, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x05, 0x20,
-	0x01, 0x28, 0x03, 0x52, 0x06, 0x70, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x69,
-	0x73, 0x46, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52,
+	0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x62, 0x75, 0x79, 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x70,
+	0x72, 0x6f, 0x76, 0x69, 0x6e, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70,
+	0x72, 0x6f, 0x76, 0x69, 0x6e, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x69, 0x74, 0x79, 0x18,
+	0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x69, 0x74, 0x79, 0x12, 0x1e, 0x0a, 0x0a, 0x69,
+	0x73, 0x46, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52,
 	0x0a, 0x69, 0x73, 0x46, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x69,
-	0x73, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52,
+	0x73, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52,
 	0x0a, 0x69, 0x73, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x72,
-	0x65, 0x63, 0x49, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x72, 0x65, 0x63, 0x49,
-	0x64, 0x32, 0x45, 0x0a, 0x07, 0x42, 0x78, 0x62, 0x75, 0x79, 0x65, 0x72, 0x12, 0x3a, 0x0a, 0x09,
-	0x42, 0x75, 0x79, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x15, 0x2e, 0x62, 0x78, 0x62, 0x75,
-	0x79, 0x65, 0x72, 0x2e, 0x42, 0x75, 0x79, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71,
-	0x1a, 0x16, 0x2e, 0x62, 0x78, 0x62, 0x75, 0x79, 0x65, 0x72, 0x2e, 0x42, 0x75, 0x79, 0x65, 0x72,
-	0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x42, 0x0b, 0x5a, 0x09, 0x2e, 0x2f, 0x62, 0x78,
-	0x62, 0x75, 0x79, 0x65, 0x72, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+	0x65, 0x63, 0x49, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x72, 0x65, 0x63, 0x49,
+	0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x62, 0x75, 0x79, 0x65, 0x72, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x18,
+	0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x62, 0x75, 0x79, 0x65, 0x72, 0x43, 0x6c, 0x61, 0x73,
+	0x73, 0x12, 0x22, 0x0a, 0x0c, 0x62, 0x69, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x75, 0x6e,
+	0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x62, 0x69, 0x64, 0x64, 0x69, 0x6e, 0x67,
+	0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x22, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74,
+	0x43, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x63, 0x6f, 0x6e,
+	0x74, 0x61, 0x63, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x22, 0x0a, 0x0c, 0x70, 0x72, 0x6f,
+	0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52,
+	0x0c, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x26, 0x0a,
+	0x0e, 0x62, 0x69, 0x64, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x18,
+	0x0b, 0x20, 0x01, 0x28, 0x02, 0x52, 0x0e, 0x62, 0x69, 0x64, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74,
+	0x43, 0x6f, 0x75, 0x6e, 0x74, 0x32, 0x45, 0x0a, 0x07, 0x42, 0x78, 0x62, 0x75, 0x79, 0x65, 0x72,
+	0x12, 0x3a, 0x0a, 0x09, 0x42, 0x75, 0x79, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x15, 0x2e,
+	0x62, 0x78, 0x62, 0x75, 0x79, 0x65, 0x72, 0x2e, 0x42, 0x75, 0x79, 0x65, 0x72, 0x4c, 0x69, 0x73,
+	0x74, 0x52, 0x65, 0x71, 0x1a, 0x16, 0x2e, 0x62, 0x78, 0x62, 0x75, 0x79, 0x65, 0x72, 0x2e, 0x42,
+	0x75, 0x79, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x42, 0x0b, 0x5a, 0x09,
+	0x2e, 0x2f, 0x62, 0x78, 0x62, 0x75, 0x79, 0x65, 0x72, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+	0x33,
 }
 
 var (

+ 1 - 1
jyBXBuyer/rpc/type/bxbuyer/bxbuyer_grpc.pb.go

@@ -1,7 +1,7 @@
 // Code generated by protoc-gen-go-grpc. DO NOT EDIT.
 // versions:
 // - protoc-gen-go-grpc v1.2.0
-// - protoc             v3.15.5
+// - protoc             v3.19.4
 // source: bxbuyer.proto
 
 package bxbuyer