queryStruct.go 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. package service
  2. import (
  3. "app.yhyue.com/moapp/jybase/encrypt"
  4. "context"
  5. "fmt"
  6. "github.com/gogf/gf/v2/container/gvar"
  7. "github.com/gogf/gf/v2/frame/g"
  8. "github.com/gogf/gf/v2/util/gconv"
  9. "jybxseo/internal/consts"
  10. "jybxseo/utility"
  11. "strings"
  12. )
  13. type (
  14. SeoBiddingQuery struct {
  15. keys string
  16. area string
  17. city string
  18. district string
  19. topType string
  20. subType string
  21. topClass string
  22. subClass string
  23. }
  24. InfoList struct {
  25. Title string
  26. Url string
  27. Area string
  28. Industry string
  29. Subtype string
  30. Price string
  31. Site string
  32. Detail string
  33. Keyword string
  34. FileExists bool
  35. PublishTime int64
  36. }
  37. ListResp struct {
  38. Total int
  39. List []*InfoList
  40. }
  41. )
  42. func NewBiddingQuery() *SeoBiddingQuery {
  43. return &SeoBiddingQuery{}
  44. }
  45. // EquipArea 装备地区查询
  46. func (query *SeoBiddingQuery) EquipArea(areaNode *AreaNode) *SeoBiddingQuery {
  47. if areaNode.Type == 2 {
  48. query.city = areaNode.Name
  49. } else {
  50. query.area = areaNode.Name
  51. }
  52. return query
  53. }
  54. func (query *SeoBiddingQuery) EquipKeyWord(keyword string) *SeoBiddingQuery {
  55. query.keys = keyword
  56. return query
  57. }
  58. func (query *SeoBiddingQuery) EquipIndustry(topClass, subClass string) *SeoBiddingQuery {
  59. if topClass != "" {
  60. query.topClass = topClass
  61. }
  62. if subClass != "" {
  63. query.subClass = subClass
  64. }
  65. return query
  66. }
  67. func (query *SeoBiddingQuery) dataFormat(data []map[string]interface{}) (bList []*InfoList) {
  68. if len(data) > 0 {
  69. titleReduction := map[string]bool{}
  70. for _, v := range data {
  71. bl := &InfoList{
  72. Title: gconv.String(v["title"]),
  73. Url: fmt.Sprintf("/nologin/content/%s.html", encrypt.CommonEncodeArticle("content", gconv.String(v["bid_id"]))),
  74. Area: gconv.String(v["area"]),
  75. Subtype: gconv.String(v["subtype"]),
  76. Detail: gconv.String(v["desc"]),
  77. Keyword: gconv.String(v["keyword"]),
  78. }
  79. //重复标题加数字后缀
  80. if titleReduction[bl.Title] {
  81. continue
  82. }
  83. titleReduction[bl.Title] = true
  84. bl.PublishTime = gconv.Int64(v["publish_time"])
  85. if gconv.String(v["area"]) == "剑鱼信息发布平台" {
  86. bl.Site = "用户发布"
  87. }
  88. if industry := gconv.String(v["industry"]); industry != "" {
  89. bl.Industry = industry
  90. }
  91. if isValidFile, _ := v["isValidFile"].(bool); isValidFile {
  92. bl.FileExists = true
  93. }
  94. if budget := gconv.Float64(v["budget"]); budget > 0 {
  95. bl.Price = utility.ConversionMoney(v["budget"])
  96. } else if bidamount := gconv.Float64(v["bidamount"]); bidamount > 0 {
  97. bl.Price = utility.ConversionMoney(v["bidamount"])
  98. }
  99. bList = append(bList, bl)
  100. }
  101. }
  102. return
  103. }
  104. // getBidListCacheKey 获取列表缓存
  105. func (query *SeoBiddingQuery) getDataPageListCacheKey(pageNum, maxTotal int, flag string) string {
  106. return fmt.Sprintf("JySeoBidDataPageList_%s_%d_%d_%s_%s_%s_%s_%s_%s_%s_%s", flag, pageNum, maxTotal, query.keys, query.area, query.city, query.district, query.topType, query.subType, query.topClass, query.subClass)
  107. }
  108. // GetDataPageList 翻页列表页查询
  109. // 一次性查询全部信息,生成每页cache
  110. func (query *SeoBiddingQuery) GetDataPageList(ctx context.Context, pageNum, maxTotal int, flag string, getData func(context.Context, int, *SeoBiddingQuery) []map[string]interface{}) (res *ListResp, err error) {
  111. var vars *gvar.Var
  112. res = &ListResp{}
  113. vars, err = g.Redis().Get(ctx, query.getDataPageListCacheKey(pageNum, maxTotal, flag))
  114. if err != nil || vars.IsNil() {
  115. //并发限制
  116. if ok := utility.JySeoQueryListLimit.Limit(); !ok {
  117. err = fmt.Errorf("请求超时")
  118. return
  119. }
  120. defer utility.JySeoQueryListLimit.Reset()
  121. data := getData(ctx, maxTotal, query)
  122. formatData := query.dataFormat(data)
  123. count := len(formatData)
  124. if count > maxTotal {
  125. count = maxTotal
  126. }
  127. if data != nil && len(data) > 0 {
  128. totalPage := count / consts.SettingPageSize
  129. if count%consts.SettingPageSize != 0 {
  130. totalPage++
  131. }
  132. for i := 1; i <= gconv.Int(totalPage); i++ {
  133. start, end := (i-1)*consts.SettingPageSize, (i)*consts.SettingPageSize
  134. if end > count {
  135. end = count
  136. }
  137. pageTmp := &ListResp{
  138. Total: totalPage,
  139. List: formatData[start:end],
  140. }
  141. if i == pageNum {
  142. res = pageTmp
  143. }
  144. if err := g.Redis().SetEX(ctx, query.getDataPageListCacheKey(i, maxTotal, flag), pageTmp, consts.SettingBidCacheTime); err != nil {
  145. g.Log().Errorf(ctx, "第%d页数据 存储redis err:%v", err)
  146. }
  147. }
  148. }
  149. } else {
  150. err = vars.Struct(res)
  151. }
  152. return
  153. }
  154. // getTabDataCacheKey 获取列表缓存
  155. func (query *SeoBiddingQuery) getOnceDataCacheKey(total int, flag string) string {
  156. return fmt.Sprintf("JySeoBidDataOnceList_%s_%d_%s_%s_%s_%s_%s_%s_%s_%s", flag, total, query.keys, query.area, query.city, query.district, query.topType, query.subType, query.topClass, query.subClass)
  157. }
  158. // GetOnceData 获取数据
  159. func (query *SeoBiddingQuery) GetOnceData(ctx context.Context, total int, flag string, getData func(context.Context, int, *SeoBiddingQuery) []map[string]interface{}) (res []*InfoList, err error) {
  160. var vars *gvar.Var
  161. cacheKey := query.getOnceDataCacheKey(total, flag)
  162. vars, err = g.Redis().Get(ctx, cacheKey)
  163. if err != nil || vars.IsNil() {
  164. //并发限制
  165. if ok := utility.JySeoQueryTabLimit.Limit(); !ok {
  166. err = fmt.Errorf("请求超时")
  167. return
  168. }
  169. defer utility.JySeoQueryTabLimit.Reset()
  170. data := getData(ctx, total, query)
  171. if len(data) > total {
  172. data = data[:total]
  173. }
  174. if data != nil && len(data) > 0 {
  175. res = query.dataFormat(data)
  176. }
  177. if err := g.Redis().SetEX(ctx, cacheKey, res, consts.SettingBidCacheTime); err != nil {
  178. g.Log().Errorf(ctx, "GetOnceData 存储redis err:%v", err)
  179. }
  180. } else {
  181. err = vars.Struct(&res)
  182. }
  183. return
  184. }
  185. func FillingBiddingBaseFields(ctx context.Context, res []map[string]interface{}) []map[string]interface{} {
  186. bidIdStrings := make([]string, 0, len(res))
  187. for _, m := range res {
  188. if bidId := gconv.String(m["bid_id"]); bidId != "" {
  189. bidIdStrings = append(bidIdStrings, bidId)
  190. }
  191. }
  192. bidRes, _ := g.DB().Query(ctx, fmt.Sprintf(`SELECT * FROM jyseo.new_bidList WHERE toptype !='拟建' AND toptype !='采购意向' AND bid_id IN ('%s')`, strings.Join(bidIdStrings, "','")))
  193. if bidRes.IsEmpty() {
  194. return nil
  195. }
  196. bidMap := map[string]map[string]interface{}{}
  197. for _, m := range bidRes.List() {
  198. if bidIdStr := gconv.String(m["bid_id"]); bidIdStr != "" {
  199. bidMap[bidIdStr] = m
  200. }
  201. }
  202. var finalArr []map[string]interface{}
  203. for i := 0; i < len(res); i++ {
  204. if tBid := gconv.String(res[i]["bid_id"]); tBid != "" && bidMap[tBid] != nil && len(bidMap[tBid]) > 0 {
  205. for k, v := range bidMap[tBid] {
  206. res[i][k] = v
  207. }
  208. finalArr = append(finalArr, res[i])
  209. }
  210. }
  211. return finalArr
  212. }
  213. func FillingEsBiddingBaseFields(res []map[string]interface{}, key string) []map[string]interface{} {
  214. bidMap := map[string]map[string]interface{}{}
  215. for _, m := range res {
  216. if bidIdStr := gconv.String(m["_id"]); bidIdStr != "" {
  217. mv := make(map[string]interface{})
  218. mv["keyword"] = key
  219. if len([]rune(gconv.String(m["detail"]))) > 100 {
  220. mv["desc"] = string([]rune(gconv.String(m["detail"]))[:100])
  221. } else {
  222. mv["desc"] = gconv.String(m["detail"])
  223. }
  224. mv["bid_id"] = bidIdStr
  225. mv["title"] = gconv.String(m["title"])
  226. mv["area"] = gconv.String(m["area"])
  227. mv["city"] = gconv.String(m["city"])
  228. mv["district"] = gconv.String(m["district"])
  229. mv["toptype"] = gconv.String(m["toptype"])
  230. mv["subtype"] = gconv.String(m["subtype"])
  231. mv["industry"] = ""
  232. if subs := gconv.String(m["s_subscopeclass"]); subs != "" {
  233. classArr := strings.Split(strings.Split(subs, ",")[0], "_")
  234. if len(classArr) == 2 {
  235. mv["industry"] = classArr[0]
  236. }
  237. }
  238. mv["bidamount"] = gconv.Float64(m["bidamount"])
  239. mv["budget"] = gconv.Float64(m["budget"])
  240. mv["size"] = gconv.String(m["size"])
  241. mv["isValidFile"] = gconv.Bool(m["isValidFile"])
  242. mv["publish_time"] = gconv.Int64(m["publishtime"])
  243. bidMap[bidIdStr] = mv
  244. }
  245. }
  246. var finalArr []map[string]interface{}
  247. for i := 0; i < len(res); i++ {
  248. if tBid := gconv.String(res[i]["_id"]); tBid != "" && bidMap[tBid] != nil && len(bidMap[tBid]) > 0 {
  249. for k, v := range bidMap[tBid] {
  250. res[i][k] = v
  251. }
  252. finalArr = append(finalArr, res[i])
  253. }
  254. }
  255. return finalArr
  256. }