Selaa lähdekoodia

Merge remote-tracking branch 'origin/master'

# Conflicts:
#	go.mod
#	go.sum
WH01243 2 vuotta sitten
vanhempi
commit
54fd665836

+ 185 - 82
common/src/qfw/util/dataexport/dataexport.go

@@ -22,6 +22,18 @@ import (
 	"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    = "拟建项目,采购意向"
+)
+
 /*筛选条件--关键词*/
 type KeyWord struct {
 	Keyword  string   `json:"keyword"`  //关键词
@@ -55,6 +67,9 @@ type SieveCondition struct {
 	FileExists       string    `json:"fileExists"`       //是否有附件
 	SearchTypeSwitch bool      `json:"searchTypeSwitch"` //是否开启 正文 标题同时搜索只搜正文的开关
 	BidField         string    `json:"bid_field"`        // 领域化数据 0101-医疗行业
+	SearchGroup      int       `json:"searchGroup"`      // 搜索分组:默认0:全部;1:招标采购公告;2:超前项目
+	SearchMode       int       `json:"searchMode"`       // 搜索模式:0:精准搜索;1:模糊搜索
+	WordsMode        int       `json:"wordsMode"`        // 搜索关键词模式;默认0:包含所有,1:包含任意
 }
 
 const (
@@ -99,12 +114,14 @@ func getDataExportSql(scd *SieveCondition) string {
 	query := `{"query":{"bool":{"must":[%s],"must_not":[%s],"should":[%s],"minimum_should_match": %d}}}`
 	//query := `{"query": {"function_score": {"query": {"bool": {"must": [%s],"must_not": [%s],"should": [%s],"minimum_should_match": %d}},"field_value_factor": {"field": "dataweight","modifier": "ln1p","missing": 0}}}}`
 	query_bool_should := `{"bool":{"should":[%s],"minimum_should_match": 1}}`
+	query_bool_should_and := `{"bool":{"should":[%s],"minimum_should_match": 1 %s}}`
 	query_price := `{"bool":{"must":[{"range":{"bidamount":{%s}}}]}},{"bool":{"must":[{"range":{"budget":{%s}}}],"must_not":[{"range":{"bidamount":{"gte":-1}}}]}}`
 	query_bool_must := `{"terms":{"%s":[%s]}}`
 	query_bool_must_and := `{"bool":{"must":[%s]%s}}`
 	query_missing := `{"constant_score":{"filter":{"missing":{"field":"%s"}}}}`
 	query_bool_must_term := `{"bool": {"must": [{ "term": {"isValidFile": %d }}]}}`
 	query_bool_must_term_bidField := `{"bool": {"must": [{ "term": {"bid_field": "%s" }}]}}` // 领域化数据类型
+
 	gte := `"gte": %s`
 	lte := `"lte": %s`
 
@@ -176,12 +193,17 @@ func getDataExportSql(scd *SieveCondition) string {
 	}
 	timequery += `}}}`
 	musts = append(musts, timequery)
-
+	if scd.Subtype == "" {
+		if scd.SearchGroup == SearchGroupBidding { // 搜索分组处理  招标采购公告 超前项目
+			scd.Subtype = TopTypesBidding
+		} else if scd.SearchGroup == SearchGroupLeadingProject {
+			scd.Subtype = TopTypesLeadingProject
+		}
+	}
 	if scd.Subtype != "" {
 		var subquery string
 		var topTypes []string
 		var subTypes []string
-
 		for _, v := range strings.Split(scd.Subtype, ",") {
 			if v1, ok := topType[v]; ok {
 				topTypes = append(topTypes, fmt.Sprintf(`"%s"`, v1))
@@ -284,27 +306,34 @@ func getDataExportSql(scd *SieveCondition) string {
 		for _, v := range scd.Keyword {
 			shoulds := []string{}
 			must_not := []string{}
+			keysShoulds := []string{}
 			if v.Keyword != "" {
 				if strings.Contains(v.Keyword, "+") {
 					for _, vk := range strings.Split(v.Keyword, "+") {
+						if len(vk) == 0 {
+							continue
+						}
 						//单个字 搜索范围 有全文或者附件 无标题 例如:学 虚拟机 detail  搜索的时候加上标题
 						if scd.Comeinfrom == "supersearchPage" && DetailFileORTitle(selectType) && len([]rune(elastic.ReplaceYH(vk))) == 1 {
 							queryItem = strings.ReplaceAll(selectType+",title", ",", "\",\"")
 							shouldsKey := fmt.Sprintf(multi_match, "\""+vk+"\"", "\""+queryItem+"\"")
-							shoulds = append(shoulds, shouldsKey)
+							keysShoulds = append(keysShoulds, shouldsKey)
 						} else {
-							shoulds = append(shoulds, fmt.Sprintf(multi_match_new, "\""+vk+"\""))
+							keysShoulds = append(keysShoulds, fmt.Sprintf(multi_match_new, "\""+vk+"\""))
 						}
 					}
 				} else if strings.Contains(v.Keyword, " ") {
 					for _, vk := range strings.Split(v.Keyword, " ") {
+						if len(vk) == 0 {
+							continue
+						}
 						//单个字 搜索范围 有全文或者附件 无标题 例如:学 虚拟机 detail  搜索的时候加上标题
 						if scd.Comeinfrom == "supersearchPage" && DetailFileORTitle(selectType) && len([]rune(elastic.ReplaceYH(vk))) == 1 {
 							queryItem = strings.ReplaceAll(selectType+",title", ",", "\",\"")
 							shouldsKey := fmt.Sprintf(multi_match, "\""+vk+"\"", "\""+queryItem+"\"")
-							shoulds = append(shoulds, shouldsKey)
+							keysShoulds = append(keysShoulds, shouldsKey)
 						} else {
-							shoulds = append(shoulds, fmt.Sprintf(multi_match_new, "\""+vk+"\""))
+							keysShoulds = append(keysShoulds, fmt.Sprintf(multi_match_new, "\""+vk+"\""))
 						}
 					}
 				} else {
@@ -312,28 +341,76 @@ func getDataExportSql(scd *SieveCondition) string {
 					if scd.Comeinfrom == "supersearchPage" && DetailFileORTitle(selectType) && len([]rune(elastic.ReplaceYH(v.Keyword))) == 1 {
 						queryItem = strings.ReplaceAll(selectType+",title", ",", "\",\"")
 						shouldsKey := fmt.Sprintf(multi_match, "\""+v.Keyword+"\"", "\""+queryItem+"\"")
-						shoulds = append(shoulds, shouldsKey)
+						keysShoulds = append(keysShoulds, shouldsKey)
 					} else {
-						shoulds = append(shoulds, fmt.Sprintf(multi_match_new, "\""+v.Keyword+"\""))
+						keysShoulds = append(keysShoulds, fmt.Sprintf(multi_match_new, "\""+v.Keyword+"\""))
 					}
 				}
+				// 单个关键词分词后都包含
+				shoulds = append(shoulds, fmt.Sprintf(query_bool_must_and, strings.Join(keysShoulds, ","), ""))
 			}
 
 			//附加词
 			for _, vv := range v.Appended {
-				shoulds = append(shoulds, fmt.Sprintf(multi_match_new, "\""+vv+"\""))
-			}
+				appendedShoulds := []string{}
+				if vv != "" {
+					// 附加词处理分词
+					if strings.Contains(vv, "+") {
+						for _, vk := range strings.Split(vv, "+") {
+							if len(vk) == 0 {
+								continue
+							}
+							//单个字 搜索范围 有全文或者附件 无标题 例如:学 虚拟机 detail  搜索的时候加上标题
+							if scd.Comeinfrom == "supersearchPage" && DetailFileORTitle(selectType) && len([]rune(elastic.ReplaceYH(vk))) == 1 {
+								queryItem = strings.ReplaceAll(selectType+",title", ",", "\",\"")
+								shouldsKey := fmt.Sprintf(multi_match, "\""+vk+"\"", "\""+queryItem+"\"")
+								appendedShoulds = append(appendedShoulds, shouldsKey)
+							} else {
+								appendedShoulds = append(appendedShoulds, fmt.Sprintf(multi_match_new, "\""+vk+"\""))
+							}
+						}
+					} else if strings.Contains(vv, " ") {
+						for _, vk := range strings.Split(vv, " ") {
+							if len(vk) == 0 {
+								continue
+							}
 
+							//单个字 搜索范围 有全文或者附件 无标题 例如:学 虚拟机 detail  搜索的时候加上标题
+							if scd.Comeinfrom == "supersearchPage" && DetailFileORTitle(selectType) && len([]rune(elastic.ReplaceYH(vk))) == 1 {
+								queryItem = strings.ReplaceAll(selectType+",title", ",", "\",\"")
+								shouldsKey := fmt.Sprintf(multi_match, "\""+vk+"\"", "\""+queryItem+"\"")
+								appendedShoulds = append(appendedShoulds, shouldsKey)
+							} else {
+								appendedShoulds = append(appendedShoulds, fmt.Sprintf(multi_match_new, "\""+vk+"\""))
+							}
+						}
+					} else {
+						appendedShoulds = append(appendedShoulds, fmt.Sprintf(multi_match_new, "\""+vv+"\""))
+
+					}
+					// 单个关键词分词后都包含
+					shoulds = append(shoulds, fmt.Sprintf(query_bool_must_and, strings.Join(appendedShoulds, ","), ""))
+				}
+			}
 			//排除词
 			for _, vv := range v.Exclude {
-				//单个字 搜索范围 有全文或者附件 无标题 例如:学 虚拟机 detail  搜索的时候加上标题
-				if scd.Comeinfrom == "supersearchPage" && DetailFileORTitle(selectType) && len([]rune(elastic.ReplaceYH(vv))) == 1 {
-					queryItem = strings.ReplaceAll(selectType+",title", ",", "\",\"")
-					shouldsKey := fmt.Sprintf(multi_match, "\""+vv+"\"", "\""+queryItem+"\"")
-					shoulds = append(shoulds, shouldsKey)
-				} else {
-					must_not = append(must_not, fmt.Sprintf(multi_match_new, "\""+vv+"\""))
+				if len(strings.TrimSpace(vv)) == 0 {
+					continue
+				} // 处理每组里面的空格分词
+				for _, notKeySplit := range strings.Split(vv, " ") {
+					if len(notKeySplit) == 0 {
+						continue
+					}
+					//单个字 搜索范围 有全文或者附件 无标题 例如:学 虚拟机 detail  搜索的时候加上标题
+					if scd.Comeinfrom == "supersearchPage" && DetailFileORTitle(selectType) && len([]rune(elastic.ReplaceYH(notKeySplit))) == 1 {
+						queryItem = strings.ReplaceAll(selectType+",title", ",", "\",\"")
+						shouldsKey := fmt.Sprintf(multi_match, "\""+notKeySplit+"\"", "\""+queryItem+"\"")
+						must_not = append(must_not, shouldsKey)
+					} else {
+						must_not = append(must_not, fmt.Sprintf(multi_match_new, "\""+notKeySplit+"\""))
+					}
 				}
+
 			}
 
 			//添加
@@ -342,7 +419,11 @@ func getDataExportSql(scd *SieveCondition) string {
 				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))
+				if scd.WordsMode == WordsModeOr { // 包含任意
+					bools = append(bools, fmt.Sprintf(query_bool_should_and, strings.Join(shoulds, ","), notStr))
+				} else {
+					bools = append(bools, fmt.Sprintf(query_bool_must_and, strings.Join(shoulds, ","), notStr))
+				}
 			}
 		}
 	}
@@ -374,9 +455,7 @@ func getDataExportSql(scd *SieveCondition) string {
 	}
 	// 如果是领域化数据则需要加标签
 	if scd.BidField != "" {
-
 		musts = append(musts, fmt.Sprintf(query_bool_must_term_bidField, scd.BidField))
-
 	}
 	qstr := fmt.Sprintf(query, strings.Join(musts, ","), strings.Join(must_not, ","), strings.Join(bools, ","), boolsNum)
 	return qstr
@@ -415,6 +494,9 @@ func GetSqlObjFromId(mongo mg.MongodbSim, _id string) *SieveCondition {
 		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:包含任意
 	}
 }
 
@@ -430,41 +512,46 @@ func GetDataExportSearchCountByScdId(sim, bid mg.MongodbSim, biddingName, elasti
 }
 
 func GetDataExportSearchCountBySieveCondition(scd *SieveCondition, elasticAddress string) (count int) {
-	qstr := getDataExportSql(scd)
 	if isNullSearch(scd) {
 		return -1 //程序端返回最大值
 	}
-	log.Printf("GetDataExportSearchCountUseId-%s-sql:%s\n", scd.Id, qstr)
-	count = int(elastic.Count(INDEX, TYPE, qstr))
+	if scd.SearchMode == SearchModeAccurate {
+		qstr := getDataExportSql(scd)
+		log.Printf("GetDataExportSearchCountUseId-%s-sql:%s\n", scd.Id, qstr)
+		count = int(elastic.Count(INDEX, TYPE, qstr))
+	}
+	// 依据用户选择的搜索模式和搜索范围进行匹配,即不限制只能匹配标题,且不限制最多展示100条、针对输入的单个关键词分词后需要都包含
 	//超级搜索一致的检索(防止数据导出和超级搜索数据量不一致)
-	if scd.Comeinfrom == "supersearchPage" && (len(scd.Keyword) != 0 || len(scd.Industry) != 0) {
+	if scd.Comeinfrom == "supersearchPage" && (len(scd.Keyword) != 0 || len(scd.Industry) != 0) && scd.SearchMode == SearchModeFuzzy {
 		if len(scd.Keyword) != 0 {
+			// 关键词分词
 			searchTextSize := 0
 			if len(scd.Keyword) > 0 {
 				searchTextSize = len([]rune(scd.Keyword[0].Keyword))
 			}
-			if searchTextSize > 3 && count < 50 {
-				if strings.Index(scd.SelectType, "title") > -1 {
-					var res *[]map[string]interface{}
-					if count > 0 {
-						res = doSearch(qstr, 0, count, "")
-					}
-					if secondKWS := jy.HttpEs(scd.Keyword[0].Keyword, "ik_smart", elasticAddress); secondKWS != "" {
-						scd.Keyword[0].Keyword = secondKWS
-						scd.SelectType = "title"
-						qstr = getDataExportSql(scd)
-						res2 := doSearch(qstr, 0, 100, "")
-						result := len(*delRepeatMapArr(res, res2))
-						if result > 100 {
-							result = 100
-						}
-						log.Printf("GetDataExportSearchCountUseId-%s-count:%d-分词-sql:%s\n", scd.Id, result, qstr)
-						return result
+			if searchTextSize > 0 {
+				if secondKWS := jy.HttpEs(scd.Keyword[0].Keyword, "ik_smart", elasticAddress); secondKWS != "" {
+					scd.Keyword[0].Keyword = secondKWS
+				}
+			}
+			// 附加词分词
+			for i := 0; i < len(scd.Keyword[0].Appended); i++ {
+				appendTextSize := 0
+				if len(scd.Keyword[0].Appended[i]) > 0 {
+					appendTextSize = len([]rune(scd.Keyword[0].Appended[i]))
+				}
+				if appendTextSize > 0 {
+					if secondKWS := jy.HttpEs(scd.Keyword[0].Appended[i], "ik_smart", elasticAddress); secondKWS != "" {
+						scd.Keyword[0].Appended[i] = secondKWS
 					}
 				}
 			}
-			return
+
 		}
+		qstr := getDataExportSql(scd)
+		count = int(elastic.Count(INDEX, TYPE, qstr))
+		log.Printf("GetDataExportSearchCountUseId-%s-count:%d-分词-sql:%s\n", scd.Id, count, qstr)
+		return count
 	}
 	log.Printf("GetDataExportSearchCountUseId-%s-count:%d\n", scd.Id, count)
 	return
@@ -615,37 +702,44 @@ func GetDataExportIds(elasticAddress string, scd *SieveCondition, checkCount int
 	if scd.SelectIds != nil {
 		return scd.SelectIds, nil
 	}
-	//获取查询语句
-	qstr := getDataExportSql(scd)
-	log.Printf("GetDataExportIds-%s-sql:%s\n", scd.Id, qstr)
-
-	//数据导出数据查询
-	res := doSearchByBatch(qstr, "1", checkCount, fmt.Sprintf("%s-%s", "GetDataExportSearchResult", scd.Id))
+	var qstr string
+	if scd.SearchMode == SearchModeAccurate {
+		//获取查询语句
+		qstr = getDataExportSql(scd)
+		log.Printf("GetDataExportIds-%s-sql:%s\n", scd.Id, qstr)
+	}
 	//超级搜索一致的检索(防止数据导出和超级搜索数据量不一致)
-	if scd.Comeinfrom == "supersearchPage" && (len(scd.Keyword) != 0 || len(scd.Industry) != 0) && len(scd.SelectIds) == 0 {
+	// 依据用户选择的搜索模式和搜索范围进行匹配,即不限制只能匹配标题,且不限制最多展示100条、针对输入的单个关键词分词后需要都包含
+	if scd.Comeinfrom == "supersearchPage" && (len(scd.Keyword) != 0 || len(scd.Industry) != 0) && len(scd.SelectIds) == 0 && scd.SearchMode == SearchModeFuzzy {
 		if len(scd.Keyword) != 0 {
-			num := len(res)
 			searchTextSize := 0
+			// 关键词分词
 			if len(scd.Keyword) > 0 {
 				searchTextSize = len([]rune(scd.Keyword[0].Keyword))
 			}
-			if searchTextSize > 3 && num < 50 {
-				if strings.Index(scd.SelectType, "title") > -1 {
-					if secondKWS := jy.HttpEs(scd.Keyword[0].Keyword, "ik_smart", elasticAddress); secondKWS != "" {
-						scd.Keyword[0].Keyword = secondKWS
-						scd.SelectType = "title"
-						qstr = getDataExportSql(scd)
-						log.Printf("GetDataExportIds-%s-分词查询-sql:%s\n", scd.Id, qstr)
-						res2 := doSearch(qstr, 0, 100, "")
-						res = *delRepeatMapArr(&res, res2)
-						if len(res) > 100 {
-							res = res[:100]
-						}
+			if searchTextSize > 0 {
+				if secondKWS := jy.HttpEs(scd.Keyword[0].Keyword, "ik_smart", elasticAddress); secondKWS != "" {
+					scd.Keyword[0].Keyword = secondKWS
+				}
+			}
+			// 附加词分词
+			for i := 0; i < len(scd.Keyword[0].Appended); i++ {
+				appendTextSize := 0
+				if len(scd.Keyword[0].Appended[i]) > 0 {
+					appendTextSize = len([]rune(scd.Keyword[0].Appended[i]))
+				}
+				if appendTextSize > 0 {
+					if secondKWS := jy.HttpEs(scd.Keyword[0].Appended[i], "ik_smart", elasticAddress); secondKWS != "" {
+						scd.Keyword[0].Appended[i] = secondKWS
 					}
 				}
 			}
+
 		}
+		qstr = getDataExportSql(scd)
+		log.Printf("GetDataExportIds-%s-分词查询-sql:%s\n", scd.Id, qstr)
 	}
+	res := doSearchByBatch(qstr, "1", checkCount, fmt.Sprintf("%s-%s", "GetDataExportSearchResult", scd.Id))
 	//获取信息id
 	idArr := make([]string, 0, 0)
 	for _, v := range res {
@@ -676,36 +770,45 @@ func GetDataExportSearchResult(bid mg.MongodbSim, bidMgoDBName, elasticAddress s
 		return idSelectDates, idSelectErr
 	}
 	selectType := scd.SelectType
-	//获取查询语句
-	qstr := getDataExportSql(scd)
-	log.Printf("GetDataExportSearchResult-%s-sql:%s\n", scd.Id, qstr)
-
-	//数据导出数据查询
-	res := doSearchByBatch(qstr, dataType, checkCount, fmt.Sprintf("%s-%s", "GetDataExportSearchResult", scd.Id))
+	var qstr string
+	var res []map[string]interface{}
+	if scd.SearchMode == SearchModeAccurate { // 搜索模式为精确查找
+		//获取查询语句
+		qstr = getDataExportSql(scd)
+		log.Printf("GetDataExportSearchResult-%s-sql:%s\n", scd.Id, qstr)
+		//数据导出数据查询
+		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 {
+	if scd.Comeinfrom == "supersearchPage" && (len(scd.Keyword) != 0 || len(scd.Industry) != 0) && len(scd.SelectIds) == 0 && scd.SearchMode == SearchModeFuzzy {
 		if len(scd.Keyword) != 0 {
-			num := len(res)
 			searchTextSize := 0
+			// 关键词分词
 			if len(scd.Keyword) > 0 {
 				searchTextSize = len([]rune(scd.Keyword[0].Keyword))
 			}
-			if searchTextSize > 3 && num < 50 {
-				if strings.Index(scd.SelectType, "title") > -1 {
-					if secondKWS := jy.HttpEs(scd.Keyword[0].Keyword, "ik_smart", elasticAddress); secondKWS != "" {
-						scd.Keyword[0].Keyword = secondKWS
-						scd.SelectType = "title"
-						qstr = getDataExportSql(scd)
-						log.Printf("GetDataExportSearchResult-%s-分词查询-sql:%s\n", scd.Id, qstr)
-						res2 := doSearch(qstr, 0, 100, "")
-						res = *delRepeatMapArr(&res, res2)
-						if len(res) > 100 {
-							res = res[:100]
-						}
+			if searchTextSize > 0 {
+				if secondKWS := jy.HttpEs(scd.Keyword[0].Keyword, "ik_smart", elasticAddress); secondKWS != "" {
+					scd.Keyword[0].Keyword = secondKWS
+				}
+			}
+			// 附加词分词
+			for i := 0; i < len(scd.Keyword[0].Appended); i++ {
+				appendTextSize := 0
+				if len(scd.Keyword[0].Appended[i]) > 0 {
+					appendTextSize = len([]rune(scd.Keyword[0].Appended[i]))
+				}
+				if appendTextSize > 0 {
+					if secondKWS := jy.HttpEs(scd.Keyword[0].Appended[i], "ik_smart", elasticAddress); secondKWS != "" {
+						scd.Keyword[0].Appended[i] = secondKWS
 					}
 				}
 			}
+
 		}
+		qstr = getDataExportSql(scd)
+		log.Printf("GetDataExportSearchResult-%s-分词查询-sql:%s\n", scd.Id, qstr)
+		res = doSearchByBatch(qstr, dataType, checkCount, fmt.Sprintf("%s-%s", "GetDataExportSearchResult", scd.Id))
 	}
 	//校验数量
 	if checkCount != len(res) && checkCount != -1 {

+ 79 - 39
common/src/qfw/util/jy/bigVipPower.go

@@ -1,6 +1,11 @@
 package jy
 
 import (
+	"fmt"
+	"log"
+	"strings"
+	"time"
+
 	qutil "app.yhyue.com/moapp/jybase/common"
 	"app.yhyue.com/moapp/jybase/go-xweb/httpsession"
 	m "app.yhyue.com/moapp/jybase/mongodb"
@@ -8,10 +13,7 @@ import (
 	"app.yhyue.com/moapp/jybase/redis"
 	"app.yhyue.com/moapp/jypkg/middleground"
 	"bp.jydev.jianyu360.cn/BaseService/powerCheckCenter/rpc/pb"
-	"fmt"
-	"log"
-	"strings"
-	"time"
+	userCenterBp "bp.jydev.jianyu360.cn/BaseService/userCenter/rpc/pb"
 )
 
 // 大会员状态redis缓存
@@ -27,6 +29,7 @@ type BigVipBaseMsg struct {
 	HasTrial        bool                   `json:"has_trial"`       //是否试用过
 	Customers       int                    `json:"customers"`       //可关注客户数量
 	VipStatus       int                    `json:"vip_status"`      //超级订阅状态
+	VipStartDate    int64                  `json:"vipStartDate"`    //超级订阅开始时间
 	Vip_BuySet      BuySet                 `json:"vip_buyset"`      //超级订阅套餐内容
 	EntnicheStatus  int                    `json:"entniche_status"` //商机管理状态
 	IsUpgrade       bool                   `json:"isUpgrade"`       //是否是免费用户订阅升级用户 默认true
@@ -86,6 +89,7 @@ const (
 	RedisMenuKeyWX            = "jy_workdesktopmenu_10000_WX_%s"  //剑鱼appid:10000
 	RedisMenuKeyAPP           = "jy_workdesktopmenu_10000_APP_%s" //剑鱼appid:10000
 	UserPowerRedisKey         = "jy_userpowerredis_10000_%d_%s"   //工作桌面 用户功能缓存(类似bigmember_power_3_%s)
+	PowerCheckKey             = "user_power_info_%s"              //权益校验中台缓存
 )
 
 // 初始化大会员权益
@@ -124,25 +128,14 @@ func ClearBigVipUserPower(userId string) bool {
 	redisMenuKeyWX := fmt.Sprintf(RedisMenuKeyWX, userId)
 	redisMenuKeyAPP := fmt.Sprintf(RedisMenuKeyAPP, userId)
 	userPowerRedisKey := fmt.Sprintf(UserPowerRedisKey, time.Now().Day(), userId)
-	return redis.Del(BaseInfoCacheDb, cacheKey) && redis.Del(BaseInfoCacheDb, baseInfoCacheKey) && redis.Del(BaseInfoCacheDb, redisMenuKeyPC) && redis.Del(BaseInfoCacheDb, redisMenuKeyWX) && redis.Del(BaseInfoCacheDb, redisMenuKeyAPP) && redis.Del(BaseInfoCacheDb, userPowerRedisKey)
-}
-
-// 获取商机管理个人基本信息
-func GetEntnicheState(userId string, mysql *mysql.Mysql, mg m.MongodbSim) *BigVipBaseMsg {
-	userPower := BigVipBaseMsg{}
-	userPower.EntnicheStatus = 0
-	//手机号
-	data, ok := mg.FindById("user", userId, `{"s_phone":1,"s_m_phone":1,i_member_status":1,"i_member_give":1,"s_member_mainid":1,"i_member_sub_status":1,"i_member_trial":1,"i_vip_status":1,"o_vipjy":1,"o_jy":1,"l_registedate":1}`)
-	if ok && *data != nil && len(*data) > 0 {
-		//查询是否是商机管理付费用户
-		phone, _ := qutil.If((*data)["s_phone"] != nil, (*data)["s_phone"], (*data)["s_m_phone"]).(string)
-		if phone != "" {
-			if count := mysql.CountBySql(`SELECT count(1) FROM entniche_user u LEFT JOIN entniche_info i ON u.ent_id=i.id WHERE u.phone=? and u.power=1 and i.status=1`, phone); count > 0 {
-				userPower.EntnicheStatus = 1
-			}
-		}
-	}
-	return &userPower
+	powerCheckKey := fmt.Sprintf(PowerCheckKey, userId)
+	return redis.Del(BaseInfoCacheDb, cacheKey) &&
+		redis.Del(BaseInfoCacheDb, baseInfoCacheKey) &&
+		redis.Del(BaseInfoCacheDb, redisMenuKeyPC) &&
+		redis.Del(BaseInfoCacheDb, redisMenuKeyWX) &&
+		redis.Del(BaseInfoCacheDb, redisMenuKeyAPP) &&
+		redis.Del(BaseInfoCacheDb, userPowerRedisKey) &&
+		redis.Del(BaseInfoCacheDb, powerCheckKey)
 }
 
 // 获取大会员个人基本信息
@@ -166,28 +159,24 @@ func GetBigVipUserBaseMsg(session *httpsession.Session, middleground middlegroun
 		for k, _ := range data.Member.MemberPowerList {
 			power[k] = true
 		}
-		isEnt := 0
-		if data.Entniche.PowerSource != 1 && data.Entniche.Status == 1 {
-			isEnt = 1
-		}
 		userPower = BigVipBaseMsg{
-			Status:    qutil.IntAll(data.Member.Status),    //大会员状态
-			Used:      data.Member.Used,                    //是否首次使用大会员
-			PowerMap:  power,                               //权限列表
-			ProNum:    qutil.IntAll(data.Member.ProNum),    //可关注项目数量
-			EntNum:    qutil.IntAll(data.Member.EntNum),    //可关注企业数量(取企业情报监控和企业中标动态中最大的值)
-			DailyNum:  qutil.IntAll(data.Member.DailyNum),  //数据包导出数量
-			Pid:       data.Member.Pid,                     //若为子账号此处为父节点userid
-			Uid:       userId,                              //用户id
-			HasTrial:  data.Member.IsMemberTrial == 1,      //是否试用过
-			Customers: qutil.IntAll(data.Member.Customers), //可关注客户数量
-			VipStatus: qutil.IntAll(data.Vip.Status),       //超级订阅状态
+			Status:       qutil.IntAll(data.Member.Status),    //大会员状态
+			Used:         data.Member.Used,                    //是否首次使用大会员
+			PowerMap:     power,                               //权限列表
+			ProNum:       qutil.IntAll(data.Member.ProNum),    //可关注项目数量
+			EntNum:       qutil.IntAll(data.Member.EntNum),    //可关注企业数量(取企业情报监控和企业中标动态中最大的值)
+			DailyNum:     qutil.IntAll(data.Member.DailyNum),  //数据包导出数量
+			Pid:          data.Member.Pid,                     //若为子账号此处为父节点userid
+			Uid:          userId,                              //用户id
+			HasTrial:     data.Member.IsMemberTrial == 1,      //是否试用过
+			Customers:    qutil.IntAll(data.Member.Customers), //可关注客户数量
+			VipStatus:    qutil.IntAll(data.Vip.Status),       //超级订阅状态
+			VipStartDate: data.Vip.StartTime,
 			Vip_BuySet: BuySet{
 				Upgrade:         qutil.IntAll(data.Vip.Upgrade),
 				AreaCount:       qutil.IntAll(data.Vip.Areacount),
 				BuyerclassCount: qutil.IntAll(data.Vip.Buyerclasscount),
 			}, //超级订阅套餐内容
-			EntnicheStatus:  isEnt,                    //商机管理状态
 			IsUpgrade:       data.Free.IsUpgrade,      //是否是免费用户订阅升级用户 默认true
 			Registedate:     data.Free.Registedate,    //用户注册时间
 			EntName:         data.Ent.Name,            //企业名称
@@ -216,6 +205,9 @@ func GetBigVipUserBaseMsg(session *httpsession.Session, middleground middlegroun
 				RoleId:    qutil.IntAll(data.Ent.EntRoleId),
 			}
 		}
+		if data.Entniche.Status == 1 && data.Entniche.IsEntPower == 1 {
+			userPower.EntnicheStatus = 1 //商机管理状态,
+		}
 	}
 	userPower.Data = data
 	return &userPower
@@ -258,3 +250,51 @@ func (this *BigVipBaseMsg) GetUseId() string {
 	}
 	return this.Uid
 }
+
+//根据userid获取用户基本信息
+func GetInfoForBaseUser(mgo m.MongodbSim, userid string) *userCenterBp.UserIdReq {
+	if userid == "" {
+		return nil
+	}
+	data, ok := mgo.FindById("user", userid, `{"base_user_id":1,"s_m_openid":1,"a_m_openid":1,"s_m_phone":1,"s_phone":1,"s_nickname":1,"s_jyname":1,"s_headimageurl":1,"s_headimage":1,"s_company":1,"s_password":1,"s_unionid":1}`)
+	if ok && data != nil && len(*data) > 0 {
+		userinfo := &userCenterBp.UserIdReq{
+			Appid: "10000",
+			Id:    qutil.Int64All((*data)["base_user_id"]),
+		}
+		if s_openid := qutil.ObjToString((*data)["s_m_openid"]); s_openid != "" {
+			userinfo.SOpenid = s_openid
+		}
+		if a_openid := qutil.ObjToString((*data)["a_m_openid"]); a_openid != "" {
+			userinfo.AOpenid = a_openid
+		}
+		phone := qutil.ObjToString((*data)["s_phone"])
+		if phone == "" {
+			phone = qutil.ObjToString((*data)["s_m_phone"])
+		}
+		if phone != "" {
+			userinfo.Phone = phone
+		}
+		nickname := qutil.ObjToString((*data)["s_nickname"])
+		if nickname == "" {
+			nickname = qutil.ObjToString((*data)["s_jyname"])
+		}
+		if nickname != "" {
+			userinfo.Nickname = nickname
+		}
+		if unionid := qutil.ObjToString((*data)["s_unionid"]); unionid != "" {
+			userinfo.Unionid = unionid
+		}
+		if password := qutil.ObjToString((*data)["s_password"]); password != "" {
+			userinfo.Password = password
+		}
+		if headimg := qutil.ObjToString((*data)["s_headimageurl"]); headimg != "" {
+			userinfo.Headimg = headimg
+		}
+		if company := qutil.ObjToString((*data)["s_company"]); company != "" {
+			userinfo.Company = company
+		}
+		return userinfo
+	}
+	return nil
+}

+ 7 - 3
common/src/qfw/util/jy/jy.go

@@ -52,6 +52,7 @@ func GetOldOpenid(s_m_openid, a_m_openid, s_phone string, mergeorder interface{}
 	return openid
 }
 
+var ClearHtml = regexp.MustCompile("<[^>]*>")
 var MatchSpace = regexp.MustCompile("\\s+")
 var filterReg_3 = regexp.MustCompile("(项目|公告|公示)$")
 var filterReg_2 = regexp.MustCompile("^[)\\)>》】\\]}}〕,,;;::'\"“”。.\\??、/+=\\_—*&……\\^%$¥@!!`~·(\\(<《【\\[{{〔]+$")
@@ -69,9 +70,12 @@ func FilteKey(k string) string {
 	return k
 }
 
-//超过20个字,截断
+// InterceptSearchKW 超过20个字,截断
 //返回截取后的字符串和截取掉中的前3个字
 func InterceptSearchKW(word string, keywordsLimit int, isFilter bool) (b_word, a_word, s_word string) {
+	if word == "" {
+		return
+	}
 	if isFilter {
 		word = FilteKey(word)
 	}
@@ -89,7 +93,7 @@ func InterceptSearchKW(word string, keywordsLimit int, isFilter bool) (b_word, a
 		b_word = word
 	}
 	a_word = strings.TrimSpace(a_word)
-	s_word = MatchSpace.ReplaceAllString(b_word, "+")
+	s_word = MatchSpace.ReplaceAllString(b_word, " ")
 	return
 }
 
@@ -123,7 +127,7 @@ func HttpEs(ques, analyzer, esAddress string) (res string) {
 			tokens := util.ObjArrToMapArr(resmap["tokens"].([]interface{}))
 			for _, v := range tokens {
 				token := util.ObjToString(v["token"])
-				if len([]rune(token)) == 1 && unicode.IsLetter([]rune(token)[0]) {
+				if len([]rune(token)) == 1 && !unicode.Is(unicode.Scripts["Han"], []rune(token)[0]) { //(P260保留单个汉字)
 					continue
 				}
 				if res != "" {

+ 12 - 5
common/src/qfw/util/jy/payUser.go

@@ -21,7 +21,10 @@ type VipState struct {
 	VipState     int   //超级订阅状态(1普通 2升级版)
 	BigMember    int   //大会员状态
 	EntMember    int   //商机管理用户状态
-	registerData int64 //注册时间
+	RegisterData int64 //注册时间
+	VipStartData int64 //超级订阅开始时间
+	IsNewEnt     bool  //新版商机管理
+	EntService   bool  //企业服务权限
 }
 
 func GetVipState(session *httpsession.Session, middleground middleground.Middleground, userId string) (vs *VipState) {
@@ -43,7 +46,10 @@ func GetVipState(session *httpsession.Session, middleground middleground.Middleg
 			vs.BigMember = qu.IntAll(i_member_status)
 		}
 		vs.EntMember = qu.IntAll(data.Data.Entniche.Status)
-		vs.registerData = data.Data.Free.Registedate
+		vs.RegisterData = data.Data.Free.Registedate
+		vs.VipStartData = data.VipStartDate
+		vs.IsNewEnt = data.EntIsNew
+		vs.EntService = data.IsEntService
 	}
 	return
 }
@@ -77,7 +83,7 @@ func (vs *VipState) GetQueryItems(selectType string, limitOldTime int64) (items
 		}
 		return
 	}
-	isOldUser := vs.registerData != 0 && vs.registerData < limitOldTime
+	isOldUser := vs.RegisterData != 0 && vs.RegisterData < limitOldTime
 	for _, t := range strings.Split(selectType, ",") {
 		if t == "winner" {
 			if isOldUser {
@@ -95,8 +101,9 @@ func (vs *VipState) GetQueryItems(selectType string, limitOldTime int64) (items
 }
 
 // HasBidFieldPower 获取用户是否有领域化数据权限
-func HasBidFieldPower(m *middleground.Middleground, userId int64, functionCode string) bool {
-	for _, v := range m.ResourceCenter.Haspowers(userId).Powers {
+func HasBidFieldPower(m *middleground.Middleground, sess *httpsession.Session, functionCode string) bool {
+	sessVal := sess.GetMultiple()
+	for _, v := range m.ResourceCenter.Haspowers(qu.Int64All(sessVal["accountId"]), qu.Int64All(sessVal["entAccountId"]), qu.Int64All(sessVal["entId"]), qu.Int64All(sessVal["entUserId"])).Powers {
 		if v == functionCode {
 			return true
 		}

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

@@ -23,3 +23,19 @@ func AddUser(mgo mongodb.MongodbSim, userid string, req pb.UserAddReq, middlegro
 	}
 	return false
 }
+
+//修改base-user相关参数
+func UpdateUser(mgo mongodb.MongodbSim, userid string, req pb.UserIdReq, middleground middleground.Middleground) bool {
+	if resp := middleground.UserCenter.UserUpdate(req); resp != nil {
+		return resp.Data.Status == 1
+	}
+	return false
+}
+
+//删除base-user
+func DelUser(mgo mongodb.MongodbSim, userid string, req pb.UserIdReq, middleground middleground.Middleground) bool {
+	if resp := middleground.UserCenter.UserDel(req); resp != nil {
+		return resp.Data.Status == 1
+	}
+	return false
+}

+ 52 - 29
compatible/compatible.go

@@ -51,20 +51,17 @@ func (c *Compatible) SelectByEntUserId(id string, field interface{}) *map[string
 //
 func (c *Compatible) selectDo(id string, identity *pb.Identity, fd interface{}) *map[string]interface{} {
 	field := ObjToOth(fd)
-	user := map[string]interface{}{}
 	if field == nil || len(*field) == 0 {
-		return &user
+		return nil
 	}
-	(*field)["_id"] = 0
 	if IsObjectIdHex(id) {
-		temp, ok := c.Mgo.FindById("user", id, field)
-		if ok && temp != nil && len(*temp) > 0 {
-			user = *temp
-		}
+		temp, _ := c.Mgo.FindById("user", id, field)
+		return temp
 	} else {
 		if identity == nil {
-			return &user
+			return nil
 		}
+		user := map[string]interface{}{}
 		if identity.UserId > 0 {
 			ufd := map[string]interface{}{}
 			for _, k := range []string{"s_myemail", "s_company", "s_m_openid", "s_phone", "s_m_phone", "s_unionid", "s_headimage", "s_headimageurl", "s_nickname", "l_registedate", "s_appversion", "i_ispush", "s_jyname", "s_jpushid", "s_opushid", "s_appponetype", "i_applystatus"} {
@@ -83,29 +80,52 @@ func (c *Compatible) selectDo(id string, identity *pb.Identity, fd interface{})
 			}
 		}
 		if identity.EntUserId > 0 {
-			if (*field)["o_entniche"] != nil || (*field)["o_vipjy"] != nil || (*field)["o_member_jy"] != nil || (*field)["o_jy"] != nil {
-				entniche_rule, ok := c.Mgo.Find("entniche_rule", map[string]interface{}{
+			fms := []string{}
+			fmp := map[int]map[string]interface{}{}
+			for k, v := range *field {
+				if util.IntAll(v) <= 0 {
+					continue
+				}
+				if k == "o_entniche" || strings.HasPrefix(k, "o_entniche.") {
+					if fmp[0] == nil {
+						fmp[0] = map[string]interface{}{"_id": 0}
+					}
+					fmp[0][k] = 1
+				} else if k == "o_vipjy" || strings.HasPrefix(k, "o_vipjy.") {
+					if fmp[1] == nil {
+						fmp[1] = map[string]interface{}{"_id": 0}
+					}
+					fms = append(fms, "o_vipjy")
+					fmp[1][strings.ReplaceAll(k, "o_vipjy", "o_entniche")] = 1
+				} else if k == "o_member_jy" || strings.HasPrefix(k, "o_member_jy.") {
+					if fmp[1] == nil {
+						fmp[1] = map[string]interface{}{"_id": 0}
+					}
+					fms = append(fms, "o_member_jy")
+					fmp[1][strings.ReplaceAll(k, "o_member_jy", "o_entniche")] = 1
+				} else if k == "o_jy" || strings.HasPrefix(k, "o_jy.") {
+					if fmp[2] == nil {
+						fmp[2] = map[string]interface{}{"_id": 0}
+					}
+					fmp[2][strings.ReplaceAll(k, "o_jy", "o_entniche")] = 1
+				} else {
+					continue
+				}
+			}
+			for k, v := range fmp {
+				entniche_rule, ok := c.Mgo.FindOneByField("entniche_rule", map[string]interface{}{
 					"i_userid": identity.EntUserId,
-				}, nil, `{"_id":0,"o_entniche":1,"i_type":1}`, false, -1, -1)
+					"i_type":   k,
+				}, v)
 				if ok && entniche_rule != nil && len(*entniche_rule) > 0 {
-					for _, v := range *entniche_rule {
-						i_type := util.IntAll(v["i_type"])
-						if i_type == 0 {
-							if (*field)["o_entniche"] != nil {
-								user["o_entniche"] = v["o_entniche"]
-							}
-						} else if i_type == 1 {
-							if (*field)["o_vipjy"] != nil {
-								user["o_vipjy"] = v["o_entniche"]
-							}
-							if (*field)["o_member_jy"] != nil {
-								user["o_member_jy"] = v["o_entniche"]
-							}
-						} else if i_type == 2 {
-							if (*field)["o_jy"] != nil {
-								user["o_jy"] = v["o_entniche"]
-							}
+					if k == 0 {
+						user["o_entniche"] = (*entniche_rule)["o_entniche"]
+					} else if k == 1 {
+						for _, vv := range fms {
+							user[vv] = (*entniche_rule)["o_entniche"]
 						}
+					} else if k == 2 {
+						user["o_jy"] = (*entniche_rule)["o_entniche"]
 					}
 				}
 			}
@@ -124,8 +144,11 @@ func (c *Compatible) selectDo(id string, identity *pb.Identity, fd interface{})
 				}
 			}
 		}
+		if len(user) == 0 {
+			user["0"] = 0
+		}
+		return &user
 	}
-	return &user
 }
 
 //根据mgo库user表_id,或者企业身份的职位id更新

+ 11 - 8
compatible/compatible_test.go

@@ -3,6 +3,7 @@ package compatible
 import (
 	"log"
 	"testing"
+	"time"
 
 	. "app.yhyue.com/moapp/jybase/mongodb"
 	. "app.yhyue.com/moapp/jybase/mysql"
@@ -45,16 +46,18 @@ func init() {
 }
 func TestSelect(t *testing.T) {
 	c := NewCompatible(mgo, baseService, mainMysql, middleground)
-	log.Println(c.Select("5d6378301c298a5aac7b5402", `{"s_phone":1,"i_vip_status":1,"i_member_status":1,"o_vipjy":1,"o_member_jy":1}`))
+	log.Println(c.Select("60067", `{"o_vipjy.a_items":1,"o_member_jy.a_items":1}`))
 }
 func TestUpdate(t *testing.T) {
 	c := NewCompatible(mgo, baseService, mainMysql, middleground)
-	log.Println(c.Update("935", map[string]interface{}{
-		"$inc": map[string]interface{}{
-			"test": 1,
-		},
-		"$set": map[string]interface{}{
-			"o_vipjy.test": 1,
-		},
+	saveData := map[string]interface{}{}
+	saveData["o_member_jy.a_items.0.s_item"] = "未分类"
+	saveData["o_member_jy.a_items.0.a_key.0.key"] = []string{"软件"}
+	saveData["o_member_jy.a_items.0.a_key.0.appendkey"] = []string{}
+	saveData["o_member_jy.a_items.0.a_key.0.notkey"] = []string{}
+	saveData["o_member_jy.a_items.0.a_key.0.matchway"] = 1
+	saveData["o_member_jy.a_items.0.a_key.0.updatetime"] = time.Now().Unix()
+	log.Println(c.Update("60067", map[string]interface{}{
+		"$set": saveData,
 	}))
 }

+ 38 - 0
identity/identity.go

@@ -3,7 +3,9 @@ package identity
 import (
 	"strconv"
 
+	. "app.yhyue.com/moapp/jybase/common"
 	"app.yhyue.com/moapp/jybase/go-xweb/httpsession"
+	. "app.yhyue.com/moapp/jypkg/middleground"
 	"bp.jydev.jianyu360.cn/BaseService/userCenter/rpc/pb"
 )
 
@@ -64,3 +66,39 @@ func (i *IdentityInfo) Switch(sess *httpsession.Session) bool {
 	sess.SetMultiple(m)
 	return ok
 }
+
+//切换到最优身份
+func SwitchToBest(userId int64, sess *httpsession.Session, mgd *Middleground) bool {
+	list := mgd.UserCenter.IdentityList(userId)
+	if list == nil || len(list) == 0 {
+		return false
+	}
+	if beforePositionId := Int64All(sess.Get("beforePositionId")); beforePositionId > 0 {
+		for _, v := range list {
+			if v.PositionId == beforePositionId {
+				return NewIdentityInfo(v).Switch(sess)
+			}
+		}
+	}
+	reqIds := []int64{}
+	for _, v := range list {
+		if v.PositionType == 1 {
+			reqIds = append(reqIds, v.EntUserId)
+		}
+	}
+	if len(reqIds) > 0 {
+		if resp := mgd.EntManageApplication.EmpowerUserIds(reqIds); len(resp.Ids) > 0 {
+			for _, v := range list {
+				if v.PositionType == 1 && v.EntUserId == resp.Ids[0] {
+					return NewIdentityInfo(v).Switch(sess)
+				}
+			}
+		}
+	}
+	for _, v := range list {
+		if v.PositionType == 0 {
+			return NewIdentityInfo(v).Switch(sess)
+		}
+	}
+	return false
+}

+ 54 - 0
middleground/entmanageapplication.go

@@ -0,0 +1,54 @@
+package middleground
+
+import (
+	"context"
+	"log"
+
+	"bp.jydev.jianyu360.cn/BaseService/entManageApplication/rpc/entmanageapplication"
+	"bp.jydev.jianyu360.cn/BaseService/entManageApplication/rpc/pb"
+	"github.com/zeromicro/go-zero/core/discov"
+	"github.com/zeromicro/go-zero/zrpc"
+)
+
+type entManageApplication struct {
+	hosts []string
+	key   string
+}
+
+func newEntManageApplication(hosts []string, key string) *entManageApplication {
+	return &entManageApplication{
+		hosts: hosts,
+		key:   key,
+	}
+}
+
+func (e *entManageApplication) NewClient() zrpc.Client {
+	client, err := zrpc.NewClient(zrpc.RpcClientConf{
+		Etcd: discov.EtcdConf{
+			Hosts: e.hosts,
+			Key:   e.key,
+		},
+	})
+	if err != nil {
+		log.Println(err)
+		return nil
+	}
+	return client
+}
+
+//
+func (e *entManageApplication) EmpowerUserIds(ids []int64) *pb.EmpowerUserIds {
+	client := e.NewClient()
+	if client == nil {
+		return nil
+	}
+	defer client.Conn().Close()
+	resp, err := entmanageapplication.NewEntManageApplication(client).EmpowerUserIds(context.Background(), &pb.EmpowerUserIds{
+		Ids: ids,
+	})
+	if err != nil {
+		log.Println(err)
+		return nil
+	}
+	return resp
+}

+ 9 - 4
middleground/middleground.go

@@ -1,10 +1,11 @@
 package middleground
 
 type Middleground struct {
-	hosts            []string
-	UserCenter       *userCenter
-	ResourceCenter   *resourceCenter
-	PowerCheckCenter *powerCheckCenter
+	hosts                []string
+	UserCenter           *userCenter
+	ResourceCenter       *resourceCenter
+	PowerCheckCenter     *powerCheckCenter
+	EntManageApplication *entManageApplication
 }
 
 func NewMiddleground(hosts []string) *Middleground {
@@ -24,6 +25,10 @@ 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 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")

+ 2 - 2
middleground/powercheckcenter.go

@@ -22,7 +22,7 @@ func newPowerCheckCenter(hosts []string, key string) *powerCheckCenter {
 	}
 }
 
-func (p *powerCheckCenter) newClient() zrpc.Client {
+func (p *powerCheckCenter) NewClient() zrpc.Client {
 	client, err := zrpc.NewClient(zrpc.RpcClientConf{
 		Etcd: discov.EtcdConf{
 			Hosts: p.hosts,
@@ -37,7 +37,7 @@ func (p *powerCheckCenter) newClient() zrpc.Client {
 }
 
 func (p *powerCheckCenter) Check(appid, userId string, baseUserId, accountId, entId, positionType, positionId int64) *pb.CheckResp {
-	client := p.newClient()
+	client := p.NewClient()
 	if client == nil {
 		return nil
 	}

+ 8 - 5
middleground/resourcecenter.go

@@ -22,7 +22,7 @@ func newResourceCenter(hosts []string, key string) *resourceCenter {
 	}
 }
 
-func (r *resourceCenter) newClient() zrpc.Client {
+func (r *resourceCenter) NewClient() zrpc.Client {
 	client, err := zrpc.NewClient(zrpc.RpcClientConf{
 		Etcd: discov.EtcdConf{
 			Hosts: r.hosts,
@@ -37,15 +37,18 @@ func (r *resourceCenter) newClient() zrpc.Client {
 }
 
 //
-func (r *resourceCenter) Haspowers(userId int64) *pb.HaspowersResp {
-	client := r.newClient()
+func (r *resourceCenter) Haspowers(accountId, entAccountId, entId, entUserId int64) *pb.HaspowersResp {
+	client := r.NewClient()
 	if client == nil {
 		return nil
 	}
 	defer client.Conn().Close()
 	resp, err := resource.NewResource(client).Haspowers(context.Background(), &pb.HaspowersReq{
-		Appid:  "10000",
-		UserId: userId,
+		Appid:        "10000",
+		AccountId:    accountId,
+		EntAccountId: entAccountId,
+		EntId:        entId,
+		EntUserId:    entUserId,
 	})
 	if err != nil {
 		log.Println(err)

+ 8 - 8
middleground/usercenter.go

@@ -22,7 +22,7 @@ func newUserCenter(hosts []string, key string) *userCenter {
 	}
 }
 
-func (u *userCenter) newClient() zrpc.Client {
+func (u *userCenter) NewClient() zrpc.Client {
 	client, err := zrpc.NewClient(zrpc.RpcClientConf{
 		Etcd: discov.EtcdConf{
 			Hosts: u.hosts,
@@ -38,7 +38,7 @@ func (u *userCenter) newClient() zrpc.Client {
 
 //获取身份列表
 func (u *userCenter) IdentityList(userId int64) []*pb.Identity {
-	client := u.newClient()
+	client := u.NewClient()
 	if client == nil {
 		return nil
 	}
@@ -55,7 +55,7 @@ func (u *userCenter) IdentityList(userId int64) []*pb.Identity {
 
 //获取账号id获取个人身份信息
 func (u *userCenter) IdentityByUserId(userId int64) *pb.Identity {
-	client := u.newClient()
+	client := u.NewClient()
 	if client == nil {
 		return nil
 	}
@@ -72,7 +72,7 @@ func (u *userCenter) IdentityByUserId(userId int64) *pb.Identity {
 
 //根据职位id获取身份信息
 func (u *userCenter) IdentityByPositionId(positionId int64) *pb.Identity {
-	client := u.newClient()
+	client := u.NewClient()
 	if client == nil {
 		return nil
 	}
@@ -89,7 +89,7 @@ func (u *userCenter) IdentityByPositionId(positionId int64) *pb.Identity {
 
 //根据企业员工id获取身份信息
 func (u *userCenter) IdentityByEntUserId(entUserId int64) *pb.Identity {
-	client := u.newClient()
+	client := u.NewClient()
 	if client == nil {
 		return nil
 	}
@@ -106,7 +106,7 @@ func (u *userCenter) IdentityByEntUserId(entUserId int64) *pb.Identity {
 
 //添加用户
 func (u *userCenter) UserAdd(req pb.UserAddReq) *pb.UserAddResp {
-	client := u.newClient()
+	client := u.NewClient()
 	defer client.Conn().Close()
 	resp, err := usercenter.NewUserCenter(client).UserAdd(context.Background(), &pb.UserAddReq{
 		Appid:    req.Appid,
@@ -132,7 +132,7 @@ func (u *userCenter) UserAdd(req pb.UserAddReq) *pb.UserAddResp {
 
 //修改用户
 func (u *userCenter) UserUpdate(req pb.UserIdReq) *pb.ExamineResp {
-	client := u.newClient()
+	client := u.NewClient()
 	defer client.Conn().Close()
 	resp, err := usercenter.NewUserCenter(client).UserUpdate(context.Background(), &pb.UserIdReq{
 		Appid:    req.Appid,
@@ -156,7 +156,7 @@ func (u *userCenter) UserUpdate(req pb.UserIdReq) *pb.ExamineResp {
 
 //删除用户
 func (u *userCenter) UserDel(req pb.UserIdReq) *pb.ExamineResp {
-	client := u.newClient()
+	client := u.NewClient()
 	defer client.Conn().Close()
 	resp, err := usercenter.NewUserCenter(client).UserDel(context.Background(), &pb.UserIdReq{
 		Appid: req.Appid,

+ 47 - 22
public/dataexport.go

@@ -97,23 +97,27 @@ func GetPriceDes_SieveCondition(minPrice, maxPrice string) string {
 
 //招标数据导出筛选
 type BidSearchExport struct {
-	Keywords     string //搜索词
-	Publishtime  string //发布时间
-	Area         string //地区
-	Subtype      string //信息类型
-	Minprice     string //最低价格
-	Maxprice     string //最高价格
-	Industry     string //选中的行业
-	SelectType   string //标题 or 全文
-	Winner       string //中标单位
-	Buyerclass   string //采购单位行业
-	Hasbuyertel  string //是否有采购电话
-	Haswinnertel string //是否有中标电话
-	SelectIds    string //选择单条信息id
-	Notkey       string //排除词
-	FileExists   string //是否有附件
-	City         string //城市
-	BidField     string // 领域化数据: 0101 医疗
+	Keywords        string //搜索词
+	Publishtime     string //发布时间
+	Area            string //地区
+	Subtype         string //信息类型
+	Minprice        string //最低价格
+	Maxprice        string //最高价格
+	Industry        string //选中的行业
+	SelectType      string //标题 or 全文
+	Winner          string //中标单位
+	Buyerclass      string //采购单位行业
+	Hasbuyertel     string //是否有采购电话
+	Haswinnertel    string //是否有中标电话
+	SelectIds       string //选择单条信息id
+	Notkey          string //排除词 排除词(副:五组,每组最多15个字符)
+	FileExists      string //是否有附件
+	City            string //城市
+	BidField        string // 领域化数据: 0101 医疗
+	SearchGroup     int    // 搜索分组:默认0:全部;1:招标采购公告;2:超前项目
+	SearchMode      int    // 搜索模式:0:精准搜索;1:模糊搜索
+	WordsMode       int    // 搜索关键词模式;默认0:包含所有,1:包含任意
+	AdditionalWords string // 关键词:附加关键词(副:五组,每组最多15个字符)
 }
 
 func (this *BidSearchExport) PassBidSearchExport(Sysconfig map[string]interface{}) (returnData map[string]interface{}) {
@@ -139,14 +143,32 @@ func (this *BidSearchExport) PassBidSearchExport(Sysconfig map[string]interface{
 	}
 
 	KeyWordSave := []dataexport.KeyWord{}
-	if len(this.Keywords) > 0 {
+	if len(this.Keywords) > 0 || len(this.AdditionalWords) > 0 {
 		_, _, keywords := jy.InterceptSearchKW(this.Keywords, util.IntAllDef(Sysconfig["keywordsLimit"], 35), len(this.Industry) == 0)
 		keywords = strings.Replace(keywords, "+", " ", -1)
-		excludes := []string{}
-		if this.Notkey != "" && len(strings.Split(this.Notkey, " ")) > 0 {
-			excludes = strings.Split(this.Notkey, " ")
+		excludes := []string{}    // 排除词
+		appendWords := []string{} // 附加词
+		//排除词  每组排除词不能超过15个字符
+		if this.Notkey != "" && len(strings.Split(this.Notkey, ",")) > 0 {
+			for _, ak := range strings.Split(this.Notkey, ",") {
+				if len([]rune(ak)) > 15 {
+					excludes = append(excludes, string([]rune(ak)[:15]))
+				} else {
+					excludes = append(excludes, ak)
+				}
+			}
+		}
+		//附加词 每组附加词不能超过15个字符
+		if this.AdditionalWords != "" && len(strings.Split(this.AdditionalWords, ",")) > 0 {
+			for _, ak := range strings.Split(this.AdditionalWords, ",") {
+				if len([]rune(ak)) > 15 {
+					appendWords = append(appendWords, string([]rune(ak)[:15]))
+				} else {
+					appendWords = append(appendWords, ak)
+				}
+			}
 		}
-		KeyWordSave = append(KeyWordSave, dataexport.KeyWord{Keyword: keywords, Exclude: excludes})
+		KeyWordSave = append(KeyWordSave, dataexport.KeyWord{Keyword: keywords, Exclude: excludes, Appended: appendWords})
 	}
 
 	//时间
@@ -187,6 +209,9 @@ func (this *BidSearchExport) PassBidSearchExport(Sysconfig map[string]interface{
 		"fileExists":   this.FileExists,
 		"comeintime":   now.Unix(),
 		"bid_field":    this.BidField,
+		"searchGroup":  this.SearchGroup,
+		"searchMode":   this.SearchMode,
+		"wordsMode":    this.WordsMode,
 	}
 	//选择信息id
 	if this.SelectIds != "" {