search.go 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582
  1. package util
  2. import (
  3. MC "app.yhyue.com/moapp/jybase/common"
  4. ME "app.yhyue.com/moapp/jybase/encrypt"
  5. elastic "app.yhyue.com/moapp/jybase/esv1"
  6. "crypto/rand"
  7. "encoding/json"
  8. "fmt"
  9. "github.com/zeromicro/go-zero/core/logx"
  10. "io/ioutil"
  11. IC "jyBXCore/rpc/init"
  12. "jyBXCore/rpc/type/bxcore"
  13. "log"
  14. "math/big"
  15. "net/http"
  16. "net/url"
  17. "regexp"
  18. "strconv"
  19. "strings"
  20. "time"
  21. "unicode"
  22. )
  23. var ClearHtml = regexp.MustCompile("<[^>]*>")
  24. var MatchSpace = regexp.MustCompile("\\s+")
  25. var filterReg_3 = regexp.MustCompile("(项目|公告|公示)$")
  26. var filterReg_2 = regexp.MustCompile("^[)\\)>》】\\]}}〕,,;;::'\"“”。.\\??、/+=\\_—*&……\\^%$¥@!!`~·(\\(<《【\\[{{〔]+$")
  27. var filterReg_1 = regexp.MustCompile("^([0-9]{1,3}|[零一二三四五六七八九十]{1,2}|联系人?|电话|地址|编号|采购|政府采购|成交|更正|招标|中标|变更|结果)$")
  28. var filterReg = regexp.MustCompile("^[的人号时元万公告项目地址电话邮编日期联系招标中结果成交项目项目采购采购项目政府采购公告更正公告]+$")
  29. var PhoneReg = regexp.MustCompile("^[1][3-9][0-9]{9}$")
  30. var 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})(\\]?)$")
  31. func SearchHistory(history, searchvalue string) (arrs []string) {
  32. if searchvalue != "" {
  33. arrs = strings.Split(history, ",")
  34. //新增历史记录
  35. if history == "" {
  36. arrs = make([]string, 0)
  37. }
  38. for k, v := range arrs {
  39. if v == strings.TrimSpace(searchvalue) {
  40. arrs = append(arrs[:k], arrs[k+1:]...)
  41. break
  42. }
  43. }
  44. arrs = append(arrs, searchvalue)
  45. if len(arrs) > 10 {
  46. arrs = arrs[1:11]
  47. }
  48. }
  49. return arrs
  50. }
  51. func FilteKey(k string) string {
  52. k = strings.TrimSpace(k)
  53. k = filterReg_3.ReplaceAllString(k, "")
  54. k = filterReg_2.ReplaceAllString(k, "")
  55. k = filterReg_1.ReplaceAllString(k, "")
  56. k = filterReg.ReplaceAllString(k, "")
  57. return k
  58. }
  59. //超过20个字,截断
  60. //返回截取后的字符串和截取掉中的前3个字
  61. func InterceptSearchKW(word string, isIntercept, isFilter bool) (b_word, a_word, s_word string) {
  62. if isFilter {
  63. word = FilteKey(word)
  64. }
  65. word = MatchSpace.ReplaceAllString(strings.TrimSpace(word), " ")
  66. words := []rune(word)
  67. if len(words) > 20 && isIntercept {
  68. b_word = string(words[:20])
  69. b_word = strings.TrimSpace(b_word)
  70. if len(words) > 23 {
  71. a_word = string(words[20:23])
  72. } else {
  73. a_word = string(words[20:])
  74. }
  75. } else {
  76. b_word = word
  77. }
  78. a_word = strings.TrimSpace(a_word)
  79. s_word = MatchSpace.ReplaceAllString(b_word, "+")
  80. return
  81. }
  82. func HttpEs(ques, analyzer, esAddress string) (res string) {
  83. var addrs []string
  84. surl := ""
  85. for _, s := range strings.Split(esAddress, ",") {
  86. addrs = append(addrs, s)
  87. }
  88. i, _ := rand.Int(rand.Reader, big.NewInt(int64(len(addrs)))) //随机
  89. surl = addrs[int(i.Int64())] + "/bidding/_analyze"
  90. URL, _ := url.Parse(surl)
  91. Q := URL.Query()
  92. Q.Add("text", ques)
  93. Q.Add("analyzer", analyzer)
  94. URL.RawQuery = Q.Encode()
  95. resp, err := http.Get(URL.String())
  96. if err != nil {
  97. log.Println("es连接失败 err1:", err)
  98. resp, err = getesResp(ques, analyzer, addrs)
  99. if err != nil {
  100. return
  101. }
  102. }
  103. result, err := ioutil.ReadAll(resp.Body)
  104. if err == nil {
  105. defer resp.Body.Close()
  106. var resmap map[string]interface{}
  107. json.Unmarshal(result, &resmap)
  108. if resmap != nil && resmap["tokens"] != nil {
  109. tokens := MC.ObjArrToMapArr(resmap["tokens"].([]interface{}))
  110. for _, v := range tokens {
  111. token := MC.ObjToString(v["token"])
  112. if len([]rune(token)) == 1 && unicode.IsLetter([]rune(token)[0]) {
  113. continue
  114. }
  115. if res != "" {
  116. res += "+"
  117. }
  118. res += token
  119. }
  120. }
  121. }
  122. return
  123. }
  124. //
  125. func getesResp(ques, analyzer string, addrs []string) (resp *http.Response, err error) {
  126. for _, v := range addrs {
  127. surl := v + "/bidding/_analyze"
  128. URL, _ := url.Parse(surl)
  129. Q := URL.Query()
  130. Q.Add("text", ques)
  131. Q.Add("analyzer", analyzer)
  132. URL.RawQuery = Q.Encode()
  133. resp, err = http.Get(URL.String())
  134. if err == nil {
  135. break
  136. }
  137. }
  138. return resp, err
  139. }
  140. //pc、微信、app 招标信息搜索
  141. const (
  142. INDEX = "bidding"
  143. TYPE = "bidding"
  144. bidSearch_sort = `{"publishtime":-1}`
  145. RedisName = "other"
  146. //招标搜索分页--每页显示数量
  147. SearchPageSize = 50
  148. //招标搜索分页--最大页数
  149. SearchMaxPageNum = 10 //免费用户500条记录
  150. SearchMaxPageNum_PAYED = 100 //付费用户5000条记录
  151. bidSearch_field_1 = `"_id","title","publishtime","toptype","subtype","type","area","city","s_subscopeclass","bidamount","budget","buyerclass"`
  152. bidSearch_field = bidSearch_field_1 + `,"bidopentime","winner","buyer","projectname","projectcode","projectinfo"`
  153. )
  154. //GetBidSearchData 标信息搜索
  155. func GetBidSearchData(in *bxcore.SearchReq) (count int64, list []*bxcore.SearchList) {
  156. var hightlightContent bool = false //是否高亮正文
  157. var selectTypeArr = strings.Split(in.SelectType, ",")
  158. for _, v := range selectTypeArr {
  159. if v == "detail" {
  160. hightlightContent = true
  161. break
  162. }
  163. }
  164. qstr := GetSearchQuery(in, GetBidSearchQuery(in))
  165. var start = int((in.PageNum - 1) * in.PageSize)
  166. //首页
  167. if qstr != "" && start == 0 {
  168. count = elastic.Count(INDEX, TYPE, qstr)
  169. }
  170. if count > 0 || start > 1 {
  171. field := bidSearch_field_1
  172. if start == 1 {
  173. field = bidSearch_field
  174. }
  175. var repl *[]map[string]interface{}
  176. if hightlightContent {
  177. repl = elastic.GetAllByNgram(INDEX, TYPE, qstr, `"detail"`, bidSearch_sort, field, start, int(in.PageSize), 115, true)
  178. } else {
  179. repl = elastic.GetAllByNgram(INDEX, TYPE, qstr, ``, bidSearch_sort, field, start, int(in.PageSize), 0, false)
  180. }
  181. logx.Info("------:", len(*repl))
  182. if repl != nil && *repl != nil && len(*repl) > 0 {
  183. BidListConvert(in.Industry, repl)
  184. for _, v := range *repl {
  185. //正文匹配检索关键词
  186. highlight, _ := v["highlight"].(map[string][]string)
  187. detail := ""
  188. for _, val := range highlight["detail"] {
  189. detail += ClearHtml.ReplaceAllString(val, "")
  190. }
  191. var searchList = &bxcore.SearchList{}
  192. searchList.Area = MC.ObjToString(v["area"])
  193. searchList.AreaUrl = IC.LabelMap[searchList.Area].Url
  194. searchList.BuyerClass = MC.ObjToString(v["buyerclass"])
  195. searchList.City = MC.ObjToString(v["city"])
  196. searchList.Detail = detail
  197. searchList.FileExists = v["filetext"] != nil
  198. searchList.Id = ME.EncodeArticleId2ByCheck(MC.ObjToString(v["id"]))
  199. searchList.Industry = MC.ObjToString(v["industry"])
  200. searchList.IndustryUrl = IC.LabelMap[searchList.Industry].Url
  201. searchList.PublishTime = MC.Int64All(v["publishtime"])
  202. searchList.Subtype = MC.ObjToString(v["subtype"])
  203. searchList.SubtypeUrl = IC.LabelMap[searchList.Subtype].Url
  204. searchList.Title = MC.ObjToString(v["title"])
  205. list = append(list, searchList)
  206. }
  207. }
  208. MakeCollection(in.UserId, list)
  209. logx.Info("=====:", len(list))
  210. }
  211. return
  212. }
  213. func GetBidSearchQuery(in *bxcore.SearchReq) string {
  214. query := ``
  215. //省份
  216. area := in.Province
  217. if area != "" {
  218. query += `{"terms":{"area":[`
  219. for k, v := range strings.Split(area, ",") {
  220. if k > 0 {
  221. query += `,`
  222. }
  223. query += `"` + v + `"`
  224. }
  225. query += `]}}`
  226. }
  227. //
  228. city := in.City
  229. if city != "" {
  230. if len(query) > 0 {
  231. query += ","
  232. }
  233. query += `{"terms":{"city":[`
  234. for k, v := range strings.Split(city, ",") {
  235. if k > 0 {
  236. query += `,`
  237. }
  238. query += `"` + v + `"`
  239. }
  240. query += `]}}`
  241. }
  242. //发布时间
  243. publishtime := in.PublishTime
  244. if publishtime != "" {
  245. if len(query) > 0 {
  246. query += ","
  247. }
  248. starttime, endtime := "", ""
  249. now := time.Now()
  250. if publishtime == "lately-7" { //最近7天
  251. starttime = fmt.Sprint(time.Date(now.Year(), now.Month(), now.Day()-7, 0, 0, 0, 0, time.Local).Unix())
  252. } else if publishtime == "lately-30" { //最近30天
  253. starttime = fmt.Sprint(time.Date(now.Year(), now.Month(), now.Day()-30, 0, 0, 0, 0, time.Local).Unix())
  254. } else if publishtime == "thisyear" { //最近一年
  255. starttime = fmt.Sprint(time.Date(now.Year()-1, now.Month(), now.Day(), now.Hour(), now.Minute(), now.Second(), 0, time.Local).Unix())
  256. endtime = fmt.Sprint(now.Unix())
  257. } else if publishtime == "threeyear" { //最近三年
  258. starttime = fmt.Sprint(time.Date(now.Year()-3, now.Month(), now.Day(), now.Hour(), now.Minute(), now.Second(), 0, time.Local).Unix())
  259. endtime = fmt.Sprint(now.Unix())
  260. } else if publishtime == "fiveyear" { //最近五年
  261. starttime = fmt.Sprint(time.Date(now.Year()-5, now.Month(), now.Day(), now.Hour(), now.Minute(), now.Second(), 0, time.Local).Unix())
  262. endtime = fmt.Sprint(now.Unix())
  263. } else {
  264. starttime = strings.Split(publishtime, "_")[0]
  265. endtime = strings.Split(publishtime, "_")[1]
  266. etTime := time.Now()
  267. if endtime != "" {
  268. et, _ := strconv.ParseInt(endtime, 0, 64)
  269. etTime = time.Unix(et, 0)
  270. }
  271. endtime = fmt.Sprint(time.Date(etTime.Year(), etTime.Month(), etTime.Day()+1, 0, 0, 0, 0, time.Local).Unix())
  272. }
  273. query += `{"range":{"publishtime":{`
  274. if starttime != "" {
  275. query += `"gte":` + starttime
  276. }
  277. if starttime != "" && endtime != "" {
  278. query += `,`
  279. }
  280. if endtime != "" {
  281. query += `"lt":` + endtime
  282. }
  283. query += `}}}`
  284. }
  285. //信息类型
  286. subtype := in.Subtype
  287. if subtype != "" {
  288. if len(query) > 0 {
  289. query += ","
  290. }
  291. query += `{"terms":{"subtype":[`
  292. for k, v := range strings.Split(subtype, ",") {
  293. if k > 0 {
  294. query += `,`
  295. }
  296. query += `"` + v + `"`
  297. }
  298. query += `]}}`
  299. }
  300. //
  301. //if winner != "" {
  302. // if len(query) > 0 {
  303. // query += ","
  304. // }
  305. // query += `{"terms":{"s_winner":[`
  306. // for k, v := range strings.Split(winner, ",") {
  307. // if k > 0 {
  308. // query += `,`
  309. // }
  310. // query += `"` + v + `"`
  311. // }
  312. // query += `]}}`
  313. //}
  314. //采购单位类型
  315. buyerclass := in.BuyerClass
  316. if buyerclass != "" {
  317. if len(query) > 0 {
  318. query += ","
  319. }
  320. query += `{"terms":{"buyerclass":[`
  321. for k, v := range strings.Split(buyerclass, ",") {
  322. if k > 0 {
  323. query += `,`
  324. }
  325. query += `"` + v + `"`
  326. }
  327. query += `]}}`
  328. }
  329. return query
  330. }
  331. func GetSearchQuery(in *bxcore.SearchReq, mustquery string) (qstr string) {
  332. multi_match := `{"multi_match": {"query": "%s","type": "phrase", "fields": [%s]}}`
  333. query := `{"query":{"bool":{"must":[%s],"must_not":[%s]}}}`
  334. query_bool_should := `{"bool":{"should":[%s],"minimum_should_match": 1}}`
  335. query_bools_must := `{"bool":{"must":[{"range":{"bidamount":{%s}}}]}},{"bool":{"must":[{"range":{"budget":{%s}}}],"must_not":[{"range":{"bidamount":{"gte":-1}}}]}}`
  336. query_bool_must := `{"bool":{"must":[{"terms":{"s_subscopeclass":[%s]}}]}}`
  337. query_missing := `{"constant_score":{"filter":{"missing":{"field":"%s"}}}}`
  338. gte := `"gte": %s`
  339. lte := `"lte": %s`
  340. musts, must_not := []string{}, []string{}
  341. if mustquery != "" {
  342. musts = append(musts, mustquery)
  343. }
  344. selectTypeArr := strings.Split(in.SelectType, ",")
  345. var findfields string
  346. if selectTypeArr == nil || len(selectTypeArr) == 0 {
  347. findfields = `"title"`
  348. } else {
  349. findfields = fmt.Sprintf(`"%s"`, strings.Join(selectTypeArr, "\",\""))
  350. }
  351. var isFileSearch bool = false //搜索范围是否有附件选择
  352. //此时关键词中间有+进行隔离
  353. if in.KeyWords != "" {
  354. if strings.Contains(findfields, "filetext") { //搜索范围选择附件,是否有附件条件无效;
  355. isFileSearch = true
  356. }
  357. keyword_multi_match := fmt.Sprintf(multi_match, "%s", findfields)
  358. shoulds := []string{}
  359. for _, v := range strings.Split(in.KeyWords, "+") {
  360. shoulds = append(shoulds, fmt.Sprintf(keyword_multi_match, elastic.ReplaceYH(v)))
  361. }
  362. musts = append(musts, fmt.Sprintf(elastic.NgramMust, strings.Join(shoulds, ",")))
  363. }
  364. if in.Industry != "" {
  365. industrys := strings.Split(in.Industry, ",")
  366. musts = append(musts, fmt.Sprintf(query_bool_must, `"`+strings.Join(industrys, `","`)+`"`))
  367. }
  368. //价格
  369. if in.Price != "" {
  370. minprice, maxprice := strings.Split(in.Price, "-")[0], strings.Split(in.Price, "-")[1]
  371. if minprice != "" || maxprice != "" {
  372. sq := ``
  373. if minprice != "" {
  374. min, _ := strconv.ParseFloat(minprice, 64)
  375. minprice = fmt.Sprintf("%.0f", min*10000)
  376. if minprice == "0" {
  377. minprice = ""
  378. }
  379. }
  380. if maxprice != "" {
  381. max, _ := strconv.ParseFloat(maxprice, 64)
  382. maxprice = fmt.Sprintf("%.0f", max*10000)
  383. if maxprice == "0" {
  384. maxprice = ""
  385. }
  386. }
  387. if minprice != "" {
  388. sq += fmt.Sprintf(gte, minprice)
  389. }
  390. if minprice != "" && maxprice != "" {
  391. sq += `,`
  392. }
  393. if maxprice != "" {
  394. sq += fmt.Sprintf(lte, maxprice)
  395. }
  396. if minprice != "" || maxprice != "" {
  397. query_price := fmt.Sprintf(query_bool_should, fmt.Sprintf(query_bools_must, sq, sq))
  398. musts = append(musts, query_price)
  399. }
  400. }
  401. }
  402. hasBuyerTel := in.BuyerTel
  403. if hasBuyerTel != "" {
  404. if hasBuyerTel == "y" {
  405. must_not = append(must_not, fmt.Sprintf(query_missing, "buyertel"))
  406. } else {
  407. musts = append(musts, fmt.Sprintf(query_missing, "buyertel"))
  408. }
  409. }
  410. hasWinnerTel := in.WinnerTel
  411. if hasWinnerTel != "" {
  412. if hasWinnerTel == "y" {
  413. must_not = append(must_not, fmt.Sprintf(query_missing, "winnertel"))
  414. } else {
  415. musts = append(musts, fmt.Sprintf(query_missing, "winnertel"))
  416. }
  417. }
  418. //排除词
  419. notkey := in.ExclusionWords
  420. if notkey = strings.TrimSpace(notkey); notkey != "" {
  421. notkey_multi_match := fmt.Sprintf(multi_match, "%s", findfields)
  422. notkey_must_not := []string{}
  423. for _, v := range strings.Split(notkey, " ") {
  424. v = strings.TrimSpace(v)
  425. if v == "" {
  426. continue
  427. }
  428. notkey_must_not = append(notkey_must_not, fmt.Sprintf(notkey_multi_match, elastic.ReplaceYH(v)))
  429. }
  430. must_not = append(must_not, fmt.Sprintf(query_bool_should, strings.Join(notkey_must_not, ",")))
  431. }
  432. //
  433. fileExists := in.FileExists
  434. if !isFileSearch && fileExists != "" {
  435. if fileExists == "1" { //有附件
  436. must_not = append(must_not, fmt.Sprintf(query_missing, "filetext"))
  437. } else if fileExists == "-1" { //无附件
  438. musts = append(musts, fmt.Sprintf(query_missing, "filetext"))
  439. }
  440. }
  441. qstr = fmt.Sprintf(query, strings.Join(musts, ","), strings.Join(must_not, ","))
  442. logx.Info(qstr)
  443. return
  444. }
  445. /*
  446. * 结果列表转换,目前只换行行业字段
  447. * 所有的招标搜索都要调用此方法,列表中有展示行业的也可以用
  448. * industry 搜索条件中的行业,默认为空
  449. */
  450. func BidListConvert(industry string, res *[]map[string]interface{}) {
  451. if res == nil {
  452. return
  453. }
  454. commonSubstring := func(v string) (value string) {
  455. bcs := strings.Split(v, "_")
  456. if len(bcs) == 1 {
  457. value = bcs[0]
  458. } else if len(bcs) == 2 {
  459. value = bcs[0]
  460. if strings.TrimSpace(value) == "" {
  461. value = bcs[0]
  462. }
  463. }
  464. return
  465. }
  466. for _, v := range *res {
  467. v["id"] = v["_id"]
  468. delete(v, "_id")
  469. budget, _ := v["budget"].(float64)
  470. bidamount, _ := v["bidamount"].(float64)
  471. if budget == 0 || strings.TrimSpace(fmt.Sprint(v["budget"])) == "" {
  472. delete(v, "budget")
  473. }
  474. if bidamount == 0 || strings.TrimSpace(fmt.Sprint(v["bidamount"])) == "" {
  475. delete(v, "bidamount")
  476. }
  477. value := ""
  478. subscopeclass, _ := v["s_subscopeclass"].(string)
  479. subscopeclass = strings.Trim(subscopeclass, ",")
  480. bct := strings.Split(subscopeclass, ",")
  481. if bct == nil || len(bct) == 0 {
  482. continue
  483. }
  484. //搜索条件中没有行业的话,取查询结果中第一个行业
  485. if industry == "" {
  486. value = commonSubstring(bct[0])
  487. } else { //搜索条件中有行业的话,取行业中和搜索条件相对应的第一个
  488. industrys := strings.Split(industry, ",")
  489. L:
  490. for _, bc := range bct {
  491. for _, is := range industrys {
  492. if bc == is {
  493. value = commonSubstring(bc)
  494. break L
  495. }
  496. }
  497. }
  498. }
  499. if strings.TrimSpace(value) == "" {
  500. continue
  501. }
  502. v["industry"] = value
  503. }
  504. }
  505. //是否收藏
  506. func MakeCollection(userId string, list []*bxcore.SearchList) {
  507. if list == nil || len(list) == 0 {
  508. return
  509. }
  510. param := []interface{}{userId}
  511. wh := []string{}
  512. for _, v := range list {
  513. array := ME.DecodeArticleId2ByCheck(v.Id)
  514. if len(array) == 1 && array[0] != "" {
  515. param = append(param, array[0])
  516. wh = append(wh, "?")
  517. }
  518. }
  519. if len(wh) > 0 {
  520. result := IC.MainMysql.SelectBySql(`select bid from bdcollection where userid=? and bid in (`+strings.Join(wh, ",")+`)`, param...)
  521. bid_map := map[string]bool{}
  522. if result != nil {
  523. for _, v := range *result {
  524. bid_map[ME.EncodeArticleId2ByCheck(MC.ObjToString(v["bid"]))] = true
  525. }
  526. }
  527. for _, v := range list {
  528. if bid_map[v.Id] {
  529. v.IsCollected = true
  530. }
  531. }
  532. }
  533. }
  534. //默认查询缓存数据
  535. func SearchCahcheData(in *bxcore.SearchReq) (count int64, list []*bxcore.SearchList) {
  536. //最新招标信息
  537. findfields := `"title"`
  538. qstr := GetSearchQuery(in, GetBidSearchQuery(in))
  539. //首页
  540. if in.PageNum == 1 {
  541. count = elastic.Count(INDEX, TYPE, qstr)
  542. }
  543. if count > 0 || in.PageNum > 1 {
  544. repl := elastic.GetAllByNgram(INDEX, TYPE, qstr, findfields, bidSearch_sort, bidSearch_field, int(in.PageNum), int(in.PageSize), 0, false)
  545. if repl != nil && *repl != nil && len(*repl) > 0 {
  546. BidListConvert(in.Industry, repl)
  547. for _, v := range *repl {
  548. var searchList = &bxcore.SearchList{}
  549. searchList.Area = MC.ObjToString(v["area"])
  550. searchList.AreaUrl = IC.LabelMap[searchList.Area].Url
  551. searchList.BuyerClass = MC.ObjToString(v["buyerclass"])
  552. searchList.City = MC.ObjToString(v["city"])
  553. searchList.FileExists = v["filetext"] != nil
  554. searchList.Id = ME.EncodeArticleId2ByCheck(MC.ObjToString(v["id"]))
  555. searchList.Industry = MC.ObjToString(v["industry"])
  556. searchList.IndustryUrl = IC.LabelMap[searchList.Industry].Url
  557. searchList.PublishTime = MC.Int64All(v["publishtime"])
  558. searchList.Subtype = MC.ObjToString(v["subtype"])
  559. searchList.SubtypeUrl = IC.LabelMap[searchList.Subtype].Url
  560. searchList.Title = MC.ObjToString(v["title"])
  561. list = append(list, searchList)
  562. }
  563. }
  564. }
  565. return
  566. }