queryStruct.go 8.2 KB

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