search.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. package util
  2. import (
  3. "fmt"
  4. IC "jyBXCore/rpc/init"
  5. "jyBXCore/rpc/internal/config"
  6. "jyBXCore/rpc/type/bxcore"
  7. "net/http"
  8. "net/url"
  9. "regexp"
  10. "strconv"
  11. "strings"
  12. "time"
  13. MC "app.yhyue.com/moapp/jybase/common"
  14. ME "app.yhyue.com/moapp/jybase/encrypt"
  15. "app.yhyue.com/moapp/jybase/es"
  16. "github.com/zeromicro/go-zero/core/logx"
  17. )
  18. var (
  19. ClearHtml = regexp.MustCompile("<[^>]*>")
  20. MatchSpace = regexp.MustCompile("\\s+")
  21. filterReg3 = regexp.MustCompile("(项目|公告|公示)$")
  22. filterReg2 = regexp.MustCompile("^[)\\)>》】\\]}}〕,,;;::'\"“”。.\\??、/+=\\_—*&……\\^%$¥@!!`~·(\\(<《【\\[{{〔]+$")
  23. filterReg1 = regexp.MustCompile("^([0-9]{1,3}|[零一二三四五六七八九十]{1,2}|联系人?|电话|地址|编号|采购|政府采购|成交|更正|招标|中标|变更|结果)$")
  24. filterReg = regexp.MustCompile("^[的人号时元万公告项目地址电话邮编日期联系招标中结果成交项目项目采购采购项目政府采购公告更正公告]+$")
  25. //PhoneReg = regexp.MustCompile("^[1][3-9][0-9]{9}$")
  26. //EmailPattern = regexp.MustCompile("^([a-zA-Z0-9_\\-\\.]+)@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.)|(([a-zA-Z0-9\\-]+\\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\\]?)$")
  27. )
  28. // SearchHistory 格式化 关键词搜索历史记录
  29. func SearchHistory(history, searchValue, additionalWords string) (arrS []string) {
  30. //主关键词
  31. var searchKeys = strings.Split(searchValue, IC.C.JYKeyMark)
  32. //附加词
  33. if additionalWords != "" {
  34. for _, aws := range strings.Split(additionalWords, ",") {
  35. for _, as := range strings.Split(aws, IC.C.JYKeyMark) {
  36. searchKeys = append(searchKeys, as)
  37. }
  38. }
  39. }
  40. //关键词 和 附加词 合并,作为新的关键词历史搜索记录
  41. if len(searchKeys) > 0 {
  42. arrS = strings.Split(history, ",")
  43. //新增历史记录
  44. if history == "" {
  45. arrS = make([]string, 0)
  46. }
  47. for _, sv := range searchKeys {
  48. for k, v := range arrS {
  49. if v == strings.TrimSpace(sv) {
  50. arrS = append(arrS[:k], arrS[k+1:]...)
  51. break
  52. }
  53. }
  54. }
  55. arrS = append(arrS, searchKeys...)
  56. if len(arrS) > 10 {
  57. arrS = arrS[len(arrS)-10:]
  58. }
  59. }
  60. return arrS
  61. }
  62. func FilterKey(k string) string {
  63. k = strings.TrimSpace(k)
  64. k = filterReg3.ReplaceAllString(k, "")
  65. k = filterReg2.ReplaceAllString(k, "")
  66. k = filterReg1.ReplaceAllString(k, "")
  67. k = filterReg.ReplaceAllString(k, "")
  68. return k
  69. }
  70. // InterceptSearchKW 超过keywordsLimit个字,截断
  71. // 返回截取后的字符串和截取掉中的前3个字
  72. // b_word:截取后的关键词;a_word:截取后 后面三个字;s_word:已截取 处理过的关键词
  73. func InterceptSearchKW(word string, keywordsLimit int, isFilter bool) (bWord, aWord, sWord string) {
  74. if isFilter {
  75. word = FilterKey(word)
  76. }
  77. word = MatchSpace.ReplaceAllString(strings.TrimSpace(word), " ")
  78. words := []rune(word)
  79. if len(words) > keywordsLimit {
  80. bWord = string(words[:keywordsLimit])
  81. bWord = strings.TrimSpace(bWord)
  82. if len(words) > keywordsLimit+3 {
  83. aWord = string(words[keywordsLimit : keywordsLimit+3])
  84. } else {
  85. aWord = string(words[keywordsLimit:])
  86. }
  87. } else {
  88. bWord = word
  89. }
  90. aWord = strings.TrimSpace(aWord)
  91. sWord = MatchSpace.ReplaceAllString(bWord, IC.C.JYKeyMark)
  92. return
  93. }
  94. func HttpEs(ques, analyzer, esAddress string) (res string) {
  95. return es.Analyze(ques, "bidding", analyzer)
  96. }
  97. func getESResp(ques, analyzer string, adds []string) (resp *http.Response, err error) {
  98. for _, v := range adds {
  99. curl := v + "/bidding/_analyze"
  100. URL, _ := url.Parse(curl)
  101. Q := URL.Query()
  102. Q.Add("text", ques)
  103. Q.Add("analyzer", analyzer)
  104. URL.RawQuery = Q.Encode()
  105. resp, err = http.Get(URL.String())
  106. if err == nil {
  107. break
  108. }
  109. }
  110. return resp, err
  111. }
  112. const (
  113. RedisName = "other"
  114. RedisNameNew = "newother"
  115. SearchPageSize = 50 //招标搜索分页--每页显示数量
  116. //招标搜索分页--最大页数
  117. SearchMaxPageNum = 10 //免费用户500条记录
  118. SearchMaxPageNum_PAYED = 100 //付费用户5000条记录
  119. )
  120. // MakeCollection 是否收藏
  121. func MakeCollection(userId string, list []*bxcore.SearchList) {
  122. if userId == "" {
  123. return
  124. }
  125. if list == nil || len(list) == 0 {
  126. return
  127. }
  128. param := []interface{}{userId}
  129. var wh []string
  130. for _, v := range list {
  131. logx.Info(v.Title, "---v.id---:", v.Id)
  132. array := ME.DecodeArticleId2ByCheck(v.Id)
  133. if len(array) == 1 && array[0] != "" {
  134. param = append(param, array[0])
  135. wh = append(wh, "?")
  136. }
  137. }
  138. if len(wh) > 0 {
  139. result := IC.MainMysql.SelectBySql(`select bid from bdcollection where userid=? and bid in (`+strings.Join(wh, ",")+`)`, param...)
  140. bidMap := map[string]bool{}
  141. if result != nil {
  142. for _, v := range *result {
  143. bidMap[ME.EncodeArticleId2ByCheck(MC.ObjToString(v["bid"]))] = true
  144. }
  145. }
  146. for _, v := range list {
  147. if bidMap[v.Id] {
  148. v.IsCollected = true
  149. }
  150. }
  151. }
  152. }
  153. // IndustryFormat 行业处理
  154. func IndustryFormat(industry, subScopeClass string) (newIndustry string) {
  155. commonSubstring := func(v string) (value string) {
  156. bcs := strings.Split(v, "_")
  157. if len(bcs) == 1 {
  158. value = bcs[0]
  159. } else if len(bcs) == 2 {
  160. value = bcs[0]
  161. if strings.TrimSpace(value) == "" {
  162. value = bcs[0]
  163. }
  164. }
  165. return
  166. }
  167. bct := strings.Split(subScopeClass, ",")
  168. if bct == nil || len(bct) == 0 {
  169. return
  170. }
  171. //搜索条件中没有行业的话,取查询结果中第一个行业
  172. if industry == "" {
  173. newIndustry = commonSubstring(bct[0])
  174. } else { //搜索条件中有行业的话,取行业中和搜索条件相对应的第一个
  175. industryArr := strings.Split(industry, ",")
  176. L:
  177. for _, bc := range bct {
  178. for _, is := range industryArr {
  179. if bc == is {
  180. newIndustry = strings.TrimSpace(commonSubstring(bc))
  181. break L
  182. }
  183. }
  184. }
  185. }
  186. return
  187. }
  188. // SearchListFormat 格式化数据
  189. func SearchListFormat(userid, industry string, repl *[]map[string]interface{}, b bool) (list []*bxcore.SearchList) {
  190. for _, v := range *repl {
  191. var searchList = &bxcore.SearchList{}
  192. //正文
  193. if b {
  194. //正文匹配检索关键词
  195. highlight, _ := v["highlight"].(map[string][]string)
  196. detail := ""
  197. for _, val := range highlight["detail"] {
  198. detail += ClearHtml.ReplaceAllString(val, "")
  199. }
  200. searchList.Detail = detail
  201. }
  202. searchList.Id = ME.EncodeArticleId2ByCheck(MC.ObjToString(v["_id"])) //ME.EncodeArticleId2ByCheck(MC.ObjToString(v["_id"])) //加密信息id
  203. searchList.Area = MC.ObjToString(v["area"]) //地区
  204. searchList.AreaUrl = IC.LabelMap[searchList.Area].Url //地区分类链接
  205. searchList.BuyerClass = MC.ObjToString(v["buyerclass"]) //采购单位类型
  206. searchList.City = MC.ObjToString(v["city"]) //城市
  207. searchList.Industry = IndustryFormat(industry, strings.Trim(MC.ObjToString(v["s_subscopeclass"]), ",")) //行业
  208. searchList.IndustryUrl = IC.LabelMap[searchList.Industry].Url //行业分类地址
  209. searchList.PublishTime = MC.Int64All(v["publishtime"]) //发布时间
  210. searchList.FileExists, _ = v["isValidFile"].(bool) //是否有附件
  211. searchList.Subtype = MC.ObjToString(v["subtype"]) //信息类型
  212. searchList.SubtypeUrl = IC.LabelMap[searchList.Subtype].Url //信息类型分类链接
  213. searchList.Title = MC.ObjToString(v["title"]) //标题
  214. searchList.ProjectName = MC.ObjToString(v["projectname"]) //项目名称
  215. searchList.ProjectCode = MC.ObjToString(v["projectcode"]) //项目代码
  216. if budget, ok := v["budget"].(float64); ok && budget > 0 { //预算
  217. searchList.Budget = int64(budget)
  218. }
  219. if bidAmount, ok := v["bidamount"].(float64); ok && bidAmount > 0 { //中标金额
  220. searchList.BidAmount = int64(bidAmount)
  221. }
  222. searchList.Buyer = MC.ObjToString(v["buyer"]) //采购单位
  223. searchList.BuyerTel = MC.ObjToString(v["buyertel"]) //采购单位联系方式
  224. searchList.BuyerPerson = MC.ObjToString(v["buyerperson"]) //采购单位联系人
  225. searchList.Agency = MC.ObjToString(v["agency"]) //代理机构
  226. searchList.AgencyTel = MC.ObjToString(v["agencytel"]) //代理机构联系电话
  227. searchList.AgencyPerson = MC.ObjToString(v["agencyperson"]) //代理机构联系人
  228. searchList.BidOpenTime = MC.Int64All(v["bidopentime"]) //开标时间
  229. searchList.BidEndTime = MC.Int64All(v["bidendtime"]) //发布时间
  230. searchList.SignEndTime = MC.Int64All(v["signendtime"]) //投标截止日期
  231. searchList.Site = MC.ObjToString(v["site"]) //网站来源名称
  232. searchList.SpiderCode = MC.ObjToString(v["spidercode"]) //网站来源代码
  233. searchList.Winner = MC.ObjToString(v["winner"]) //中标企业
  234. winnerList := MC.ObjToString(v["s_winner"]) //中标企业名称集合
  235. if winnerList != "" && len(strings.Split(winnerList, ",")) > 0 {
  236. for wk, wv := range strings.Split(winnerList, ",") {
  237. var (
  238. winnerId = ""
  239. )
  240. if v["entidlist"] != nil {
  241. if entIdList := MC.ObjArrToStringArr(v["entidlist"].([]interface{})); len(entIdList) > wk { //中标企业id集合
  242. winnerId = entIdList[wk]
  243. }
  244. }
  245. searchList.WinnerInfo = append(searchList.WinnerInfo, &bxcore.WinnerInfo{
  246. Winner: wv, //中标企业 需要单独处理
  247. WinnerTel: MC.ObjToString(v["winnertel"]), //中标企业联系电话
  248. WinnerPerson: MC.ObjToString(v["winnerperson"]), //中标企业联系人
  249. WinnerId: MC.If(winnerId != "" && len([]rune(winnerId)) > 12, ME.EncodeArticleId2ByCheck(winnerId), "").(string), //中标企业加密id 存在winnerId 异常的情况
  250. })
  251. }
  252. }
  253. searchList.ProjectInfo = &bxcore.PInfo{} //拟建项目信息
  254. if v["projectinfo"] != nil {
  255. pInfo := MC.ObjToMap(v["projectinfo"])
  256. searchList.ProjectInfo.ApproveCode = MC.ObjToString((*pInfo)["approvecode"])
  257. searchList.ProjectInfo.ApproveContent = MC.ObjToString((*pInfo)["approvecontent"])
  258. searchList.ProjectInfo.ApproveDept = MC.ObjToString((*pInfo)["approvedept"])
  259. searchList.ProjectInfo.ApproveStatus = MC.ObjToString((*pInfo)["approvestatus"])
  260. searchList.ProjectInfo.ProjectType = MC.ObjToString((*pInfo)["projecttype"])
  261. searchList.ProjectInfo.ApproveNumber = MC.ObjToString((*pInfo)["approvenumber"])
  262. searchList.ProjectInfo.ApproveTime = MC.ObjToString((*pInfo)["approvetime"])
  263. }
  264. list = append(list, searchList)
  265. }
  266. return
  267. }
  268. // IsOptimize 付费用户搜索优化
  269. // 需求来源:付费用户 默认查询 五年内数据,数据查询耗时,
  270. // 付费用户 且开关打开,针对前两页数据,满足关键词(< 7个字),查询时间范围一年以上,缩短查询时间
  271. func IsOptimize(cc config.Config, in *bxcore.SearchReq) bool {
  272. if cc.PaySearchLimit.Switch && in.UserType != "fType" {
  273. //首页----字数(<7)
  274. if in.PageNum <= cc.PaySearchLimit.PageNum && len([]rune(in.KeyWords)) < cc.PaySearchLimit.WordSize {
  275. //时间超过一年----
  276. if pTime := GetPublishTime(cc.PaySearchLimit.Year, cc.PaySearchLimit.Month, in.PublishTime); pTime != "" {
  277. in.PublishTime = pTime
  278. return true
  279. }
  280. }
  281. }
  282. return false
  283. }
  284. // GetPublishTime 查询时间调整
  285. func GetPublishTime(y, m int, publishTime string) string {
  286. //发布时间
  287. timeArray := strings.Split(publishTime, "-")
  288. if len(timeArray) == 2 {
  289. startTime, err1 := strconv.ParseInt(timeArray[0], 10, 64)
  290. endTime, err2 := strconv.ParseInt(timeArray[1], 10, 64)
  291. if err1 == nil && err2 == nil {
  292. if endTime == 0 {
  293. endTime = time.Now().Unix()
  294. }
  295. //重新计算数据查询 开始时间
  296. pTime := time.Unix(endTime, 0).AddDate(y, m, 0).Unix()
  297. //从新定义搜索时间跨度
  298. if endTime-startTime > pTime {
  299. return fmt.Sprintf("%d-%d", pTime, endTime)
  300. }
  301. }
  302. }
  303. return ""
  304. }