dataServiceArea.go 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540
  1. package front
  2. import (
  3. "app.yhyue.com/moapp/jybase/common"
  4. "app.yhyue.com/moapp/jybase/redis"
  5. "app.yhyue.com/moapp/jypkg/public"
  6. "encoding/json"
  7. "fmt"
  8. "jy/src/jfw/jyutil"
  9. "math/rand"
  10. "strings"
  11. //_ "github.com/gogf/gf/contrib/drivers/clickhouse/v2"
  12. "github.com/gogf/gf/v2/frame/g"
  13. "github.com/gogf/gf/v2/os/gctx"
  14. "github.com/gogf/gf/v2/util/gconv"
  15. "jy/src/jfw/config"
  16. )
  17. // HotIndustryAndRegion 热门行业/地区年度招标趋势
  18. func HomeBiddingTrends() []config.IndustryTrend {
  19. return config.IndustryTrendConfig
  20. }
  21. type (
  22. KeyWordSiteRoot struct {
  23. SiteCodeMap map[string]*KeyWordSiteNode //省份直辖市简称对照
  24. SiteArr []*KeyWordSiteNode
  25. }
  26. KeyWordSiteNode struct {
  27. Code string `json:"code" doc:"代码"`
  28. Alias string `json:"alias" doc:"名称"`
  29. AreaKeyWord string `json:"areaKeyword" doc:"省份关键词"`
  30. CityKeyWord string `json:"cityKeyword" doc:"城市关键词"`
  31. CitySpecialKeyWord string `json:"citySpecialKeyword" doc:"直辖市关键词"`
  32. NotShowCityCode map[string]bool `json:"notShowCityCode" doc:"不展示的城市,因数据量少"`
  33. }
  34. KeyWordSiteShow struct {
  35. Code string `json:"code" doc:"代码"`
  36. Name string `json:"name" doc:"名称"`
  37. //KeyWord string `json:"keyWord" doc:"对应关键词"`
  38. }
  39. argument struct {
  40. Name string
  41. Url string
  42. }
  43. keyBidding struct {
  44. code string
  45. area string
  46. city string
  47. district string
  48. }
  49. keyFw struct {
  50. code string
  51. keyword string
  52. }
  53. )
  54. var (
  55. siteCodeMap map[string]*KeyWordSiteNode
  56. specialArea = map[string]bool{"北京": true, "上海": true, "天津": true, "重庆": true}
  57. KeyBiddingAreaMap []keyBidding
  58. KeyFwArr []keyFw
  59. KeyJyMap map[string]string
  60. DistrictSArr []keyFw
  61. )
  62. func init() {
  63. siteCodeMap = make(map[string]*KeyWordSiteNode)
  64. KeyJyMap = make(map[string]string)
  65. res, err := g.DB().Query(gctx.New(), `SELECT * FROM seo_siteKeywords_splicing order by site_code asc`)
  66. if err == nil && len(res.List()) > 0 {
  67. for _, m := range res.List() {
  68. notShowCityCodeMap := map[string]bool{}
  69. for _, cityCode := range strings.Split(gconv.String(m["notShowCityCode"]), ",") {
  70. notShowCityCodeMap[cityCode] = true
  71. }
  72. node := &KeyWordSiteNode{
  73. Code: fmt.Sprintf("S%s", gconv.String(m["site_code"])),
  74. Alias: gconv.String(m["alias"]),
  75. AreaKeyWord: gconv.String(m["area"]),
  76. CityKeyWord: gconv.String(m["city"]),
  77. CitySpecialKeyWord: gconv.String(m["city_special"]),
  78. NotShowCityCode: notShowCityCodeMap,
  79. }
  80. siteCodeMap[node.Code] = node
  81. }
  82. }
  83. KeyBiddingArea, _ := config.Sysconfig["keyBiddingArea"].(string)
  84. resArr, err := g.DB().Query(gctx.New(), fmt.Sprintf(`SELECT area ,city,district,pcode FROM seo_area_code where state = 1 and class = 4 and area in ('%s') %s`, strings.ReplaceAll(KeyBiddingArea, ",", `','`), `and (district LIKE '%县%' or district LIKE '%市%')`))
  85. if err == nil && !resArr.IsEmpty() {
  86. for _, m := range resArr.List() {
  87. KeyBiddingAreaMap = append(KeyBiddingAreaMap, keyBidding{
  88. area: gconv.String(m["area"]),
  89. city: gconv.String(m["city"]),
  90. district: gconv.String(m["district"]),
  91. code: gconv.String(m["pcode"]),
  92. })
  93. }
  94. }
  95. districtSData, err := g.DB().Query(gctx.New(), `SELECT site_code,keywords,alias FROM seo_siteKeywords_district where site_code = 1 `)
  96. if err == nil && !districtSData.IsEmpty() {
  97. for _, m := range districtSData.List() {
  98. DistrictSArr = append(DistrictSArr, keyFw{
  99. keyword: gconv.String(m["keywords"]),
  100. code: fmt.Sprintf("%s_S%d", m["alias"], m["site_code"]),
  101. })
  102. }
  103. }
  104. fwResArr, err := g.DB().Query(gctx.New(), `SELECT id, keyword FROM new_keyword_unified where unifiedSign = 'fw' and state = 1`)
  105. if err == nil && !fwResArr.IsEmpty() {
  106. for _, m := range fwResArr.List() {
  107. KeyFwArr = append(KeyFwArr, keyFw{
  108. keyword: gconv.String(m["keyword"]),
  109. code: gconv.String(m["id"]),
  110. })
  111. }
  112. }
  113. //区县教育局
  114. districtJyResArr, err := g.DB().Query(gctx.New(), `SELECT alias,keywords FROM seo_siteKeywords_district where site_code = 12`)
  115. if err == nil && !districtJyResArr.IsEmpty() {
  116. for _, m := range districtJyResArr.List() {
  117. KeyJyMap[gconv.String(m["alias"])] = gconv.String(m["keywords"])
  118. }
  119. }
  120. }
  121. type ClassCode struct {
  122. Class int
  123. Code string
  124. Url string
  125. }
  126. // 政府招标
  127. func GovernmentTender(number int) []argument {
  128. redisKey := "governmentTender"
  129. redisData := redis.Get(RedisNameNew, redisKey)
  130. if redisData != nil {
  131. if d, err := json.Marshal(redisData); err == nil {
  132. var signature []argument
  133. json.Unmarshal(d, &signature)
  134. return signature
  135. }
  136. }
  137. areaM := make(map[string]ClassCode)
  138. res, err := g.DB().Query(gctx.New(), `SELECT area,city,pcode,class FROM seo_area_code where state = 1 and (class = 1 or class = 2 or class = 3)`)
  139. if !res.IsEmpty() && len(res.List()) > 0 && err == nil {
  140. for _, v := range res.List() {
  141. switch common.IntAll(v["class"]) {
  142. case 1, 3:
  143. name := common.ObjToString(v["area"])
  144. areaM[name] = ClassCode{
  145. Class: common.IntAll(v["class"]),
  146. Code: common.ObjToString(v["pcode"]),
  147. Url: "/list/area/%s_%s",
  148. }
  149. default:
  150. name := common.ObjToString(v["city"])
  151. areaM[name] = ClassCode{
  152. Class: common.IntAll(v["class"]),
  153. Code: common.ObjToString(v["pcode"]),
  154. Url: "/list/city/%s_%s",
  155. }
  156. }
  157. }
  158. }
  159. var (
  160. data []argument
  161. upperLimit int
  162. )
  163. siteCode := make(map[string]bool)
  164. for name, acronym := range areaM {
  165. upperLimit++
  166. if upperLimit > number {
  167. break
  168. }
  169. if len(siteCode) < len(siteCodeMap) {
  170. for code, node := range siteCodeMap {
  171. var tagName string
  172. if node.NotShowCityCode[acronym.Code] {
  173. continue
  174. }
  175. if !siteCode[code] {
  176. if node.Alias != "" {
  177. tagName = node.Alias
  178. } else {
  179. switch acronym.Class {
  180. case 1:
  181. tagName = node.AreaKeyWord
  182. case 2:
  183. tagName = node.CityKeyWord
  184. case 3:
  185. tagName = node.CitySpecialKeyWord
  186. }
  187. }
  188. data = append(data, argument{
  189. fmt.Sprintf("%s%s", name, tagName),
  190. fmt.Sprintf(acronym.Url, acronym.Code, code),
  191. })
  192. siteCode[code] = true
  193. break
  194. }
  195. }
  196. } else {
  197. for code, node := range siteCodeMap {
  198. var tagName string
  199. if node.NotShowCityCode[acronym.Code] {
  200. continue
  201. }
  202. if node.Alias != "" {
  203. tagName = node.Alias
  204. } else {
  205. switch acronym.Class {
  206. case 1:
  207. tagName = node.AreaKeyWord
  208. case 2:
  209. tagName = node.CityKeyWord
  210. case 3:
  211. tagName = node.CitySpecialKeyWord
  212. }
  213. }
  214. data = append(data, argument{
  215. fmt.Sprintf("%s%s", name, tagName),
  216. fmt.Sprintf(acronym.Url, acronym.Code, code),
  217. })
  218. break
  219. }
  220. }
  221. }
  222. //随机获取10个区县教育局单位
  223. var count int
  224. for m, n := range KeyJyMap {
  225. count++
  226. if count > number {
  227. break
  228. }
  229. data = append(data, argument{
  230. n,
  231. fmt.Sprintf("/list/city/%s_S12", m),
  232. })
  233. }
  234. if len(data) > 0 {
  235. redis.Put(RedisNameNew, redisKey, data, RedisTimeout)
  236. }
  237. return data
  238. }
  239. // 重点招标区域
  240. func DistrictsTender(number int) []argument {
  241. redisKey := "districtsTender"
  242. redisData := redis.Get(RedisNameNew, redisKey)
  243. if redisData != nil {
  244. if d, err := json.Marshal(redisData); err == nil {
  245. var signature []argument
  246. json.Unmarshal(d, &signature)
  247. return signature
  248. }
  249. }
  250. var (
  251. data []argument
  252. )
  253. for _, i2 := range jyutil.GenerateRandomNumber(0, len(KeyBiddingAreaMap), number) {
  254. acronym := KeyBiddingAreaMap[i2]
  255. data = append(data, argument{
  256. common.If(strings.Contains(acronym.district, "区"), fmt.Sprintf("%s%s", acronym.city, acronym.district), acronym.district).(string),
  257. fmt.Sprintf("/list/city/%s.html", acronym.code),
  258. })
  259. }
  260. if data != nil && len(data) > 0 {
  261. redis.Put(RedisNameNew, redisKey, data, RedisTimeout)
  262. }
  263. return data
  264. }
  265. func DistrictsSList(number int) []argument {
  266. redisKey := "districtsSList"
  267. redisData := redis.Get(RedisNameNew, redisKey)
  268. if redisData != nil {
  269. if d, err := json.Marshal(redisData); err == nil {
  270. var signature []argument
  271. json.Unmarshal(d, &signature)
  272. return signature
  273. }
  274. }
  275. var (
  276. data []argument
  277. )
  278. for _, i2 := range jyutil.GenerateRandomNumber(0, len(DistrictSArr), number) {
  279. acronym := DistrictSArr[i2]
  280. data = append(data, argument{
  281. acronym.keyword,
  282. fmt.Sprintf("/list/city/%s/", acronym.code),
  283. })
  284. }
  285. if data != nil && len(data) > 0 {
  286. redis.Put(RedisNameNew, redisKey, data, RedisTimeout)
  287. }
  288. return data
  289. }
  290. /*
  291. const (
  292. PSearch_DecMust = `"bidstatus": ["中标","成交","合同","单一"]`
  293. query_bool_must = `{"terms": {%s}}`
  294. )
  295. var (
  296. industryMap map[string][]string
  297. )
  298. type ServiceRes struct {
  299. industry []industryRes
  300. }
  301. type industryRes struct {
  302. name string
  303. areas []areaRes
  304. }
  305. type areaRes struct {
  306. name string
  307. data []map[string]interface{}
  308. }
  309. type subzone struct {
  310. industry, province string
  311. }
  312. type marketBuckets struct {
  313. ProjectCount struct {
  314. DocCount int `json:"doc_count"`
  315. } `json:"project_count"`
  316. }
  317. func getQuarter(st int64) int {
  318. currentTime := time.Unix(st, 0)
  319. // 获取当前月份
  320. currentMonth := int(currentTime.Month())
  321. // 获取当前月份所属的季度
  322. return (currentMonth-1)/3 + 1
  323. }
  324. func init() {
  325. IndustryInit()
  326. BiddingTrendInit()
  327. }
  328. func BiddingTrend(st int64, et int64) {
  329. currentQuarter := getQuarter(st)
  330. for _, industry := range config.ServiceArea.Industry {
  331. ds := subzone{
  332. industry: industry,
  333. }
  334. for _, area := range config.ServiceArea.Area {
  335. ds.province = area
  336. res, _, _ := elastic.GetAggs("projectset", "projectset", GetCommonQuerySql(st, et, area, industry))
  337. if res != nil {
  338. thisRow := marketBuckets{}
  339. for name, object := range res {
  340. bArr, err := object.MarshalJSON()
  341. if len(bArr) == 0 || err != nil {
  342. break
  343. }
  344. if name == "project_count" {
  345. _ = json.Unmarshal(bArr, &thisRow.ProjectCount)
  346. quarterData := map[string]interface{}{
  347. "name": fmt.Sprintf("%d-第%d季度", time.Now().Year(), currentQuarter),
  348. "count": thisRow.ProjectCount.DocCount,
  349. }
  350. var redisDataArr []map[string]interface{}
  351. redisData, _ := redis.Get(RedisNameNew, fmt.Sprintf("biddingTrend_%s_%s", industry, area)).([]interface{})
  352. if redisData != nil && len(redisData) > 0 {
  353. redisDataArr = common.ObjArrToMapArr(redisData)
  354. if len(redisDataArr) == 4 {
  355. redisDataArr = append(redisDataArr[1:], quarterData)
  356. redis.Put(RedisNameNew, fmt.Sprintf("biddingTrend_%s_%s", industry, area), redisDataArr, 24*3600*120)
  357. continue
  358. }
  359. }
  360. redisDataArr = append(redisDataArr, quarterData)
  361. redis.Put(RedisNameNew, fmt.Sprintf("biddingTrend_%s_%s", industry, area), redisDataArr, 24*3600*120)
  362. }
  363. }
  364. }
  365. }
  366. }
  367. }
  368. func IndustryInit() {
  369. industryMap = make(map[string][]string)
  370. for _, industry := range config.ServiceArea.Industry {
  371. industryData := public.BaseMysql.SelectBySql(fmt.Sprintf(`SELECT CONCAT(b.name, '_', a.name) as name
  372. FROM global_common_data.code_bidscope a
  373. LEFT JOIN (
  374. SELECT code, name
  375. FROM global_common_data.code_bidscope
  376. WHERE name = '%s'
  377. ) b ON a.pcode = b.code
  378. WHERE b.code IS NOT NULL;`, industry))
  379. var names []string
  380. for _, v := range *industryData {
  381. names = append(names, common.InterfaceToStr(v["name"]))
  382. }
  383. industryMap[industry] = names
  384. }
  385. }
  386. func BiddingTrendInit() {
  387. for _, industry := range config.ServiceArea.Industry {
  388. ds := subzone{
  389. industry: industry,
  390. }
  391. for _, area := range config.ServiceArea.Area {
  392. ds.province = area
  393. ok, err := redis.Exists(RedisNameNew, fmt.Sprintf("biddingTrend_%s_%s", industry, area))
  394. if ok && err == nil {
  395. continue
  396. }
  397. eQuarter := Quarter()
  398. sQuarter := eQuarter.AddDate(-1, 0, 0)
  399. var redisDataArr []map[string]interface{}
  400. for sQuarter.Before(eQuarter) {
  401. currentQuarter := getQuarter(sQuarter.Unix())
  402. res, _, _ := elastic.GetAggs("projectset", "projectset", GetCommonQuerySql(sQuarter.Unix(), sQuarter.AddDate(0, 3, 0).Unix(), area, industry))
  403. if res != nil {
  404. thisRow := marketBuckets{}
  405. for name, object := range res {
  406. bArr, err := object.MarshalJSON()
  407. if len(bArr) == 0 || err != nil {
  408. break
  409. }
  410. if name == "project_count" {
  411. _ = json.Unmarshal(bArr, &thisRow.ProjectCount)
  412. quarterData := map[string]interface{}{
  413. "name": fmt.Sprintf("%d-第%d季度", sQuarter.Year(), currentQuarter),
  414. "count": thisRow.ProjectCount.DocCount,
  415. }
  416. redisDataArr = append(redisDataArr, quarterData)
  417. }
  418. }
  419. }
  420. sQuarter = sQuarter.AddDate(0, 3, 0)
  421. }
  422. redis.Put(RedisNameNew, fmt.Sprintf("biddingTrend_%s_%s", industry, area), redisDataArr, 24*3600*120)
  423. }
  424. }
  425. }
  426. // GetCommonQuerySql 公共筛选
  427. func GetCommonQuerySql(st, et int64, area, industry string) string {
  428. var musts, bools []string
  429. //时间
  430. musts = append(musts, fmt.Sprintf(`{"range":{"jgtime":{"gte":%d,"lte":%d}}}`, st, et))
  431. //地区
  432. if area != "" {
  433. musts = append(musts, fmt.Sprintf(`{"terms":{"area":["%s"]}}`, area))
  434. }
  435. //行业
  436. if len(industryMap[industry]) > 0 {
  437. musts = append(musts, fmt.Sprintf(`{"terms":{"subscopeclass":["%s"]}}`, strings.Join(industryMap[industry], `","`)))
  438. }
  439. //分析报告中标状态限制
  440. musts = append(musts, fmt.Sprintf(query_bool_must, PSearch_DecMust))
  441. aa := fmt.Sprintf(`{"query":{"bool":{"must":[%s],"should":[%s],"minimum_should_match": %d}},"aggs":{"project_count": {"filter": {"match_all":{}}}},"size":0}`, strings.Join(musts, ","), strings.Join(bools, ","), common.If(len(bools) > 0, 1, 0).(int))
  442. fmt.Println(aa)
  443. return fmt.Sprintf(`{"query":{"bool":{"must":[%s],"should":[%s],"minimum_should_match": %d}},"aggs":{"project_count": {"filter": {"match_all":{}}}},"size":0}`, strings.Join(musts, ","), strings.Join(bools, ","), common.If(len(bools) > 0, 1, 0).(int))
  444. }
  445. func Quarter() time.Time {
  446. currentTime := time.Now()
  447. // 获取当前季度
  448. currentQuarter := (currentTime.Month()-1)/3 + 1
  449. // 计算当前季度的开始时间
  450. startMonth := (currentQuarter-1)*3 + 1
  451. quarterStart := time.Date(currentTime.Year(), startMonth, 1, 0, 0, 0, 0, currentTime.Location())
  452. return quarterStart
  453. }
  454. */
  455. // 热门采购数据
  456. func PurchasingData() []map[string]interface{} {
  457. redisData, _ := redis.Get(RedisNameNew, "hotPurchasingData").([]interface{})
  458. if len(redisData) > 0 {
  459. return common.ObjArrToMapArr(redisData)
  460. }
  461. var keyWords []map[string]interface{}
  462. data := public.BaseMysql.SelectBySql("SELECT keyword FROM data_supermarket GROUP BY keyword")
  463. if data != nil && len(*data) > 0 {
  464. listData := []map[string]interface{}{}
  465. if len(*data) > 30 {
  466. r := rand.Intn(len(*data) - 30)
  467. listData = (*data)[r : r+30]
  468. } else {
  469. listData = *data
  470. }
  471. for _, m := range listData {
  472. keyWords = append(keyWords, map[string]interface{}{
  473. "keyword": common.InterfaceToStr(m["keyword"]),
  474. "url": fmt.Sprintf("/datasmt/index_1?searchValue=%s", common.InterfaceToStr(m["keyword"])),
  475. })
  476. }
  477. redis.Put(RedisNameNew, "hotPurchasingData", keyWords, RedisTimeout)
  478. }
  479. return keyWords
  480. }
  481. // ServiceProcurement 服务类采购
  482. func ServiceProcurement(number int) []argument {
  483. redisKey := "ServiceProcurement"
  484. redisData := redis.Get(RedisNameNew, redisKey)
  485. if redisData != nil {
  486. if d, err := json.Marshal(redisData); err == nil {
  487. var signature []argument
  488. json.Unmarshal(d, &signature)
  489. return signature
  490. }
  491. }
  492. var (
  493. data []argument
  494. )
  495. for _, i2 := range jyutil.GenerateRandomNumber(0, len(KeyFwArr), number) {
  496. acronym := KeyFwArr[i2]
  497. data = append(data, argument{
  498. acronym.keyword,
  499. fmt.Sprintf("/fuwu/fw%03s.html", acronym.code),
  500. })
  501. }
  502. redis.Put(RedisNameNew, redisKey, data, RedisTimeout)
  503. return data
  504. }