فهرست منبع

Merge branch 'feature/v4.7.15' of http://192.168.3.207:8080/qmx/jy into feature/v4.7.15

wangkaiyue 3 سال پیش
والد
کامیت
a4052a3b84
91فایلهای تغییر یافته به همراه6452 افزوده شده و 200 حذف شده
  1. 3 1
      src/config.json
  2. 43 0
      src/jfw/filter/baseuserfilter.go
  3. 3 0
      src/jfw/filter/filter.go
  4. 11 0
      src/jfw/front/dataExport.go
  5. 1 0
      src/jfw/front/front.go
  6. 20 1
      src/jfw/front/login.go
  7. 2 2
      src/jfw/front/pcIndex.go
  8. 11 0
      src/jfw/front/pchelper.go
  9. 89 1
      src/jfw/front/shorturl.go
  10. 1 4
      src/jfw/front/supsearch.go
  11. 2 2
      src/jfw/front/swordfish.go
  12. 9 1
      src/jfw/front/ws_dataExport.go
  13. 5 1
      src/jfw/jyutil/jyutil.go
  14. 43 0
      src/jfw/modules/app/src/app/filter/baseuserfilter.go
  15. 3 0
      src/jfw/modules/app/src/app/filter/filter.go
  16. 58 5
      src/jfw/modules/app/src/app/front/login.go
  17. 10 2
      src/jfw/modules/app/src/app/front/logoffuser.go
  18. 4 0
      src/jfw/modules/app/src/app/front/me.go
  19. 9 1
      src/jfw/modules/app/src/app/front/ws_dataExport.go
  20. 4 1
      src/jfw/modules/app/src/config.json
  21. 12 1
      src/jfw/modules/app/src/web/templates/big-member/header.html
  22. 344 0
      src/jfw/modules/app/src/web/templates/frontRouter/activity/sess/task-202207.html
  23. 0 2
      src/jfw/modules/app/src/web/templates/frontRouter/activity/sess/task.html
  24. 1 1
      src/jfw/modules/app/src/web/templates/weixin/historypush.html
  25. 50 29
      src/jfw/modules/common/src/qfw/util/bidsearch/search.go
  26. 106 52
      src/jfw/modules/common/src/qfw/util/dataexport/dataexport.go
  27. 15 14
      src/jfw/modules/common/src/qfw/util/jy/bigVipPower.go
  28. 150 1
      src/jfw/modules/common/src/qfw/util/jy/subscribepush.go
  29. 4 2
      src/jfw/modules/common/src/qfw/util/jy/userMerge.go
  30. 1 0
      src/jfw/modules/publicapply/src/ad/entity/struct.go
  31. 7 20
      src/jfw/modules/publicapply/src/bidcollection/entity/entity.go
  32. 249 0
      src/jfw/modules/publicapply/src/subscribePush/entity/historyPush.go
  33. 241 0
      src/jfw/modules/publicapply/src/subscribePush/entity/service/entity.go
  34. 260 0
      src/jfw/modules/publicapply/src/subscribePush/entity/service/matchjob.go
  35. 4 1
      src/jfw/modules/publicapply/src/subscribePush/entity/vrew.go
  36. 6 4
      src/jfw/modules/publicapply/src/subscribePush/service/pushList.go
  37. 2 1
      src/jfw/modules/subscribepay/src/config.json
  38. 1 0
      src/jfw/modules/subscribepay/src/config/config.go
  39. 49 1
      src/jfw/modules/subscribepay/src/service/userAccountInfo.go
  40. BIN
      src/jfw/modules/subscribepay/src/subscribepay
  41. 6 5
      src/jfw/modules/weixin/src/config.json
  42. 13 0
      src/jfw/modules/weixin/src/wx/wx.go
  43. 1 1
      src/jfw/public/dataexport.go
  44. BIN
      src/web/staticres/common-module/active/2022.7/button-middle@2x.png
  45. BIN
      src/web/staticres/common-module/active/2022.7/button-small@2x.png
  46. BIN
      src/web/staticres/common-module/active/2022.7/content-yure@2x.png
  47. BIN
      src/web/staticres/common-module/active/2022.7/coupon-bg@2x.png
  48. BIN
      src/web/staticres/common-module/active/2022.7/dialog-bg-big@2x.png
  49. BIN
      src/web/staticres/common-module/active/2022.7/dialog-bg@2x.png
  50. BIN
      src/web/staticres/common-module/active/2022.7/entniche-shangji@2x.png
  51. BIN
      src/web/staticres/common-module/active/2022.7/entniche-zhuanjia@2x.png
  52. BIN
      src/web/staticres/common-module/active/2022.7/float-button-bg@2x.png
  53. BIN
      src/web/staticres/common-module/active/2022.7/gift-box.png
  54. BIN
      src/web/staticres/common-module/active/2022.7/header-banner.png
  55. BIN
      src/web/staticres/common-module/active/2022.7/icon-coupon@2x.png
  56. BIN
      src/web/staticres/common-module/active/2022.7/more-fuli-text@2x.png
  57. 622 0
      src/web/staticres/common-module/active/2022.7/task-202207.css
  58. 1031 0
      src/web/staticres/common-module/active/2022.7/task-202207.js
  59. 314 0
      src/web/staticres/common-module/active/2022.7/task-common.css
  60. BIN
      src/web/staticres/common-module/active/2022.7/title-fuli1@2x.png
  61. BIN
      src/web/staticres/common-module/active/2022.7/title-fuli2@2x.png
  62. BIN
      src/web/staticres/common-module/active/2022.7/title-fuli3@2x.png
  63. BIN
      src/web/staticres/common-module/active/2022.7/title-yure@2x.png
  64. 4 0
      src/web/staticres/common-module/public/js/app-share.js
  65. 604 0
      src/web/staticres/frontRouter/pc/activity/css/task-202207.css
  66. 278 0
      src/web/staticres/frontRouter/pc/activity/css/task-common.css
  67. BIN
      src/web/staticres/frontRouter/pc/activity/image/202207/activity-rule-text@2x.png
  68. BIN
      src/web/staticres/frontRouter/pc/activity/image/202207/button-large@2x.png
  69. BIN
      src/web/staticres/frontRouter/pc/activity/image/202207/button-middle@2x.png
  70. BIN
      src/web/staticres/frontRouter/pc/activity/image/202207/button-small@2x.png
  71. BIN
      src/web/staticres/frontRouter/pc/activity/image/202207/content-yure.png
  72. BIN
      src/web/staticres/frontRouter/pc/activity/image/202207/entniche-shangji@2x.png
  73. BIN
      src/web/staticres/frontRouter/pc/activity/image/202207/entniche-zhuanjia@2x.png
  74. BIN
      src/web/staticres/frontRouter/pc/activity/image/202207/header-banner.png
  75. BIN
      src/web/staticres/frontRouter/pc/activity/image/202207/more-fuli-text@2x.png
  76. BIN
      src/web/staticres/frontRouter/pc/activity/image/202207/participate-in-text@2x.png
  77. BIN
      src/web/staticres/frontRouter/pc/activity/image/202207/strategy@2x.png
  78. BIN
      src/web/staticres/frontRouter/pc/activity/image/202207/title-fuli1@2x.png
  79. BIN
      src/web/staticres/frontRouter/pc/activity/image/202207/title-fuli2@2x.png
  80. BIN
      src/web/staticres/frontRouter/pc/activity/image/202207/title-fuli3@2x.png
  81. BIN
      src/web/staticres/frontRouter/pc/activity/image/202207/title-yure@2x.png
  82. 1002 0
      src/web/staticres/frontRouter/pc/activity/js/task-202207.js
  83. 1 3
      src/web/staticres/frontRouter/pc/coupon/js/coupon-item-template.js
  84. 38 34
      src/web/staticres/js/monitor/new_monitor.js
  85. 3 0
      src/web/staticres/public-pc/js/article-content.js
  86. 1 1
      src/web/staticres/public-pc/js/header-nav.js
  87. 369 0
      src/web/templates/frontRouter/pc/activity/sess/task-202207.html
  88. 317 0
      src/web/templates/frontRouter/wx/activity/sess/task-202207.html
  89. 11 1
      src/web/templates/pc/biddetail_rec.html
  90. 3 3
      src/web/templates/pc/supsearch.html
  91. 1 1
      src/web/templates/weixin/historypush.html

+ 3 - 1
src/config.json

@@ -321,5 +321,7 @@
     "canReadNotice": 3,
     "smsServiceRpc":"127.0.0.1:932",
     "searchTypeSwitch": true,
-    "fileSignBool":false
+    "fileSignBool":true,
+    "baseUserFilterFlag":false,
+    "userCenterApi":"https://web-zxl.jydev.jianyu360.com"
 }

+ 43 - 0
src/jfw/filter/baseuserfilter.go

@@ -0,0 +1,43 @@
+package filter
+
+import (
+	"jfw/config"
+	"jfw/public"
+	"log"
+	"net/http"
+	"qfw/util"
+
+	"github.com/go-xweb/httpsession"
+)
+
+type baseUserFilter struct {
+	W          http.ResponseWriter
+	R          *http.Request
+	Session    *httpsession.Session
+	GetSession map[string]interface{}
+}
+
+//判断session中是否存在base_user_id 不存在则更新
+
+func (this *baseUserFilter) Do() bool {
+	if flag, _ := config.Sysconfig["baseUserFilterFlag"].(bool); !flag {
+		return true
+	}
+	if this.R.Method == "POST" {
+		return true
+	}
+	if uid := this.GetSession["userId"]; uid != nil && uid != "" {
+		base_user_id := this.GetSession["base_user_id"]
+		if base_user_id == nil || base_user_id == 0 {
+			data, ok := public.MQFW.FindById("user", util.ObjToString(uid), `{"base_user_id":1}`)
+			if data != nil && ok && len(*data) > 0 {
+				if base_user_id := util.Int64All((*data)["base_user_id"]); base_user_id > 0 {
+					this.Session.Set("base_user_id", (*data)["base_user_id"])
+				} else {
+					log.Printf("%s用户暂无base_user_id", uid)
+				}
+			}
+		}
+	}
+	return true
+}

+ 3 - 0
src/jfw/filter/filter.go

@@ -52,5 +52,8 @@ func (f *Filter) Do(w http.ResponseWriter, r *http.Request) bool {
 	if !(&pcFilter{w, r, session, getSession}).Do() {
 		return false
 	}
+	if !(&baseUserFilter{w, r, session, getSession}).Do() {
+		return false
+	}
 	return true
 }

+ 11 - 0
src/jfw/front/dataExport.go

@@ -413,8 +413,19 @@ func (d *DataExport) SuperSearchExport() error {
 	saveData["s_openid"] = openid
 	saveData["s_userid"] = userId
 	saveData["comeinfrom"] = "supersearchPage"
+	//是否开启 正文 标题同时搜索只搜正文的开关
+	saveData["searchTypeSwitch"], _ = config.Sysconfig["searchTypeSwitch"].(bool)
+
+	region := util.If(reqData.Area == "全国", "", reqData.Area).(string)
+	if region != "" && reqData.City != "" {
+		region += "," + reqData.City
+	} else {
+		region = reqData.City
+	}
+	saveData["region"] = util.If(region != "", strings.Split(region, ","), []string{}).([]string)
 	//存入数据库
 	_id := mongodb.Save(dataexport.ExportTable, saveData)
+	log.Println(_id, "saveData:", saveData)
 	return d.Redirect("/front/dataExport/toCreateOrderPage/" + util.SE.Encode2Hex(_id))
 }
 func (d *DataExport) ToCreateOrderPage(_id string) error {

+ 1 - 0
src/jfw/front/front.go

@@ -655,6 +655,7 @@ func (f *Front) SignOut() error {
 	f.DelSession("entUserId")
 	f.DelSession("frameworkEntId")
 	f.DelSession("frameworkEntName")
+	f.DelSession("base_user_id")
 	f.ServeJson("ok")
 	return nil
 }

+ 20 - 1
src/jfw/front/login.go

@@ -7,6 +7,7 @@ import (
 	. "mongodb"
 	qutil "qfw/util"
 	"qfw/util/jy"
+	"qfw/util/usercenter"
 	"regexp"
 	"strings"
 	"time"
@@ -23,7 +24,6 @@ type Login struct {
 	forgetPwd xweb.Mapper `xweb:"/phone/forgetPwd"` //忘记密码
 	register  xweb.Mapper `xweb:"/phone/register"`  //注册
 	phoneBind xweb.Mapper `xweb:"/phone/bind"`      //绑定手机号
-
 }
 
 var (
@@ -132,6 +132,19 @@ func (l *Login) Login() error {
 					}
 					_id := mongodb.Save("user", data)
 					if _id != "" {
+						func(phone, userid string) {
+							//用户中台存储  开始
+							formdata := map[string]interface{}{
+								"appid": "10000",
+								"phone": phone,
+							}
+							if s_company != "" {
+								formdata["company"] = s_company
+							}
+							ck, _ := l.GetCookie("SESSIONID")
+							usercenter.AddBaseUser(mongodb, qutil.ObjToString(config.Sysconfig["userCenterApi"]), userid, formdata, ck)
+							//用户中台存储  结束
+						}(phone, _id)
 						jy.ClearPhoneIdentSession(l.Session())
 						ok, _, userInfo := afterLogin(phone, l.Session())
 						nsqPath, _ := config.Sysconfig["nsq"].(string)
@@ -249,6 +262,12 @@ func (l *Login) ForgetPwd() error {
 				"$unset": map[string]interface{}{
 					"s_m_phone": "",
 				}}, false, false) {
+				userid := BsonIdToSId(user["_id"])
+				//用户中台存储  开始
+				ck, _ := l.GetCookie("SESSIONID")
+				usercenter.UpdateBaseUser(mongodb, qutil.ObjToString(config.Sysconfig["userCenterApi"]), userid, ck)
+
+				//用户中台存储  结束
 				l.DelSession("forgetPwdStep")
 				jy.ClearPhoneIdentSession(l.Session())
 				return "y"

+ 2 - 2
src/jfw/front/pcIndex.go

@@ -151,7 +151,7 @@ func GetNewArticle(typ int) (list []map[string]interface{}) {
 	if l, ok := redis.Get("other", rediskey).([]interface{}); ok && l != nil && len(l) > 0 {
 		list = util.ObjArrToMapArr(l)
 	} else {
-		_, _, lists := bidsearch.GetPcBidSearchData("", "", "", "", subtype, "", "", "", "", "", "", "", "", 1, bidsearch.SearchPageSize_PC, false, nil, bidSearch_field_1, "", false)
+		_, _, lists := bidsearch.GetPcBidSearchData("", "", "", "", subtype, "", "", "", "", "", "", "", "", 1, bidsearch.SearchPageSize_PC, false, nil, bidSearch_field_1, "", false, false)
 		if lists != nil && len(*lists) > 5 {
 			*lists = (*lists)[0:6]
 			for _, v := range *lists {
@@ -442,7 +442,7 @@ func (f *PcIndex) SearchResult(at, name string) error {
 				// if datas != nil && len(*datas) > limitcount {
 				// 	*datas = (*datas)[0:limitcount]
 				// } else {
-				_, _, datas = bidsearch.GetPcBidSearchData(keywords, "", "", "", "", key_industry, "", "", "", "", "", "", "", 0, bidsearch.SearchPageSize_PC, true, nil, bidSearch_field_1, "", false)
+				_, _, datas = bidsearch.GetPcBidSearchData(keywords, "", "", "", "", key_industry, "", "", "", "", "", "", "", 0, bidsearch.SearchPageSize_PC, true, nil, bidSearch_field_1, "", false, false)
 				if datas != nil && len(*datas) > limitcount {
 					*datas = (*datas)[0:limitcount]
 				}

+ 11 - 0
src/jfw/front/pchelper.go

@@ -12,6 +12,7 @@ import (
 	"qfw/util"
 	"qfw/util/jy"
 	"qfw/util/redis"
+	"qfw/util/usercenter"
 	"strings"
 	"time"
 
@@ -133,6 +134,16 @@ func (l *PcHelper) Login() error {
 						}
 						_id := mongodb.Save("user", data)
 						if _id != "" {
+							//用户中台存储  开始
+							func(phone, userId string) {
+								formdata := map[string]interface{}{
+									"appid": "10000",
+									"phone": phone,
+								}
+								ck, _ := l.GetCookie("SESSIONID")
+								usercenter.AddBaseUser(mongodb, util.ObjToString(config.Sysconfig["userCenterApi"]), userId, formdata, ck)
+							}(phone, _id)
+							//用户中台存储  结束
 							jy.ClearPhoneIdentSession(l.Session())
 							reToken = getUToken(mac, phone)
 							reOpenId = phone

+ 89 - 1
src/jfw/front/shorturl.go

@@ -37,6 +37,7 @@ var mobileReg = regexp.MustCompile("(?i)(Android|Mobile|Phone)")
 var DateFullLayout = "2006-01-02 15:04:05"
 var Map_stype = map[string]bool{
 	"content":      true,
+	"entservice":   true,
 	"bdprivate":    true,
 	"mailprivate":  true,
 	"bdcontent":    true,
@@ -126,6 +127,94 @@ func (s *Short) Article(stype, id string) error {
 		if stype == "bdcontent" {
 			stype = "content"
 		}
+	} else if stype == "entservice" { //大客户数据快照展示
+		//SE := util.SimpleEncrypt{"entservice"}
+		sid := util.SE3.DecodeString(id)
+		if len(sid) == 0 || (len(sid) > 0 && sid == "") {
+			s.Redirect("/notin/page", 302)
+			return nil
+		}
+		catchKey := fmt.Sprintf("jypcdetail_%s_%s_%s", userId, stype, sid)
+		if res := redis.Get("other", catchKey); res == nil || res == "" {
+			industry := s.GetString("industry")
+			var shareid = s.GetString("id")
+			if len(shareid) == 0 {
+				shareid = "10"
+			}
+			s.T["logid"] = config.Seoconfig["jysskzy"].(string)
+			s.T["shareid"] = se.EncodeString(shareid)
+			s.T["keywords"] = s.GetString("kds")
+			ssOpenid := s.Session().Get("s_m_openid")
+
+			po, bo, wo, obj := pcVRT(sid, industry, true)
+			if obj != nil && len(obj) > 0 {
+
+				if len(po) > 0 {
+					s.T["projectOther"] = po
+				}
+				if len(bo) > 0 {
+					s.T["buyerOther"] = bo
+				}
+				if len(wo) > 0 {
+					s.T["winnerOther"] = wo
+				}
+				obj["urlpath"] = s.Uri()
+				obj["industry"] = industry
+				if ssOpenid != nil {
+					obj["ucbsId"] = util.EncodeArticleId2ByCheck("ucbs#" + ssOpenid.(string) + "#" + id)
+				}
+				if isbid(obj["subtype"]) {
+					obj["winner_enttel"] = getwinnertel(obj["winner"])
+				}
+				//判断时间 //如果是seo页面超过时间访问的进入首页
+				comeinTime := time.Unix(util.Int64All(obj["comeintime"]), 0)
+				if stype == "indexcontent" {
+					if count := public.MQFW.Count("seobidding", map[string]interface{}{"bid": sid}); count <= 0 && comeinTime.Before(time.Now().Add(time.Duration(-util.IntAll(config.Sysconfig["seoBeforeTimeHour"]))*time.Hour)) {
+						return s.Redirect("/")
+					}
+				}
+				FieldProcessing(obj, ssOpenid, industry, id, from_userid, userId, stype, true, false)
+
+				if obj["projectname"] != nil {
+					s.SetSession("projectname", obj["projectname"])
+				}
+				if obj["entidlist"] != nil { //大会员中标企业跳转至画像
+					if winner := util.ObjToString(obj["winner"]); winner != "" {
+						s_winner := util.ObjToString(obj["s_winner"])
+						idObjs, _ := obj["entidlist"].([]interface{})
+						winnerId := ""
+						if names := strings.Split(s_winner, ","); len(names) > 1 {
+							index := 0
+							for i := 0; i < len(names); i++ {
+								if names[i] == winner {
+									index = i
+									break
+								}
+							}
+							if len(idObjs) > index {
+								winnerId = util.ObjToString(idObjs[index])
+							}
+						} else { //中标企业仅一个
+							if len(idObjs) > 0 {
+								winnerId = util.ObjToString(idObjs[0])
+							}
+						}
+						if winnerId != "" && winnerId != "-" {
+							obj["entId"] = util.EncodeArticleId2ByCheck(winnerId)
+						}
+					}
+				}
+				s.T["url"] = s.Uri()
+				s.T["obj"] = obj
+
+				content, _ := s.Render4Cache("/pc/biddetail_rec.html", &s.T)
+				timeout := 60 * 20
+				redis.Put("other", catchKey, string(content), timeout)
+				return s.SetBody(content)
+			}
+		} else {
+			return s.SetBody([]byte(res.(string)))
+		}
 	}
 	ssOpenid := s.Session().Get("s_m_openid")
 	var res *map[string]interface{}
@@ -276,7 +365,6 @@ func (s *Short) Article(stype, id string) error {
 		} else {
 			nodeStr = "false"
 		}
-		fmt.Println(s.T["canRead"])
 		if userId != "" && stype == "indexcontent" { //已登录用户直接跳转至正常三级页
 			return s.Redirect(fmt.Sprintf("/article/content/%s.html", util.CommonEncodeArticle("content", sid)))
 		}

+ 1 - 4
src/jfw/front/supsearch.go

@@ -54,12 +54,9 @@ func init() {
 	PCSLock.Unlock()
 	//搜索字段添加 附件标识
 	if FileSignBool, _ = config.Sysconfig["fileSignBool"].(bool); FileSignBool {
-		log.Println(FileSignBool, "------")
 		bidSearch_field_1 = bidSearch_field_1 + bidSearch_field_file
 		bidSearch_field = bidSearch_field + bidSearch_field_file
 	}
-	log.Println("bidSearch_field_1", bidSearch_field_1)
-	log.Println("bidSearch_field", bidSearch_field)
 }
 
 //定时清理搜索列表页 从redis获取存入内存中的数据
@@ -128,7 +125,7 @@ func (p *Pcsearch) ProposedProject() error {
 	var count int64
 	if len(s_word) > 0 {
 		status = 2
-		count, totalPage, list = bidsearch.GetPcBidSearchData(s_word, area, "", publishtime, subtype, "", "", "", "", "", "", "", "", 0, bidsearch.SearchPageSize_PC, true, nil, bidSearch_field_1, "", false)
+		count, totalPage, list = bidsearch.GetPcBidSearchData(s_word, area, "", publishtime, subtype, "", "", "", "", "", "", "", "", 0, bidsearch.SearchPageSize_PC, true, nil, bidSearch_field_1, "", false, false)
 		listSize := 0
 		if list != nil {
 			listSize = len(*list)

+ 2 - 2
src/jfw/front/swordfish.go

@@ -36,7 +36,7 @@ var (
 	bidSearch_field_1    = `"_id","title","publishtime","toptype","subtype","type","area","city","s_subscopeclass","bidamount","budget","buyerclass","spidercode","site"`
 	bidSearch_field      = bidSearch_field_1 + `,"bidopentime","winner","buyer","projectname","projectcode","projectinfo"`
 	bidSearch_sort       = `{"publishtime":-1}`
-	bidSearch_field_file = `,"filetext"`
+	bidSearch_field_file = `,"filetext","isValidFile"`
 )
 
 //剑鱼标讯推送三级页点赞暂弃 改成剑鱼标讯实验室点赞功能
@@ -179,7 +179,7 @@ func (m *Front) PcAjaxReq() {
 func getLastNewsData(searchvalue, area, city, publishtime, subtype, industry, minprice, maxprice, buyerclass, hasBuyerTel, hasWinnerTel, fileExists, tabularflag string, start int, isGetCount bool, highlight bool, notkey string) (count int64, list *[]map[string]interface{}) {
 	//最新招标信息
 	findfields := `"title"`
-	qstr := bidsearch.GetSearchQuery(searchvalue, industry, minprice, maxprice, hasBuyerTel, hasWinnerTel, fileExists, findfields, bidsearch.GetBidSearchQuery(area, city, publishtime, subtype, "", buyerclass), notkey)
+	qstr := bidsearch.GetSearchQuery(searchvalue, industry, minprice, maxprice, hasBuyerTel, hasWinnerTel, fileExists, findfields, bidsearch.GetBidSearchQuery(area, city, publishtime, subtype, "", buyerclass), notkey, false)
 	if isGetCount && start == 0 {
 		count = elastic.Count(INDEX, TYPE, qstr)
 	}

+ 9 - 1
src/jfw/front/ws_dataExport.go

@@ -375,7 +375,15 @@ func (wd *WsDataExport) SearchExport() error {
 	saveData["s_openid"] = openid
 	saveData["s_userid"] = userId
 	saveData["comeinfrom"] = "supersearchPage"
-
+	region := util.If(reqData.Area == "全国", "", reqData.Area).(string)
+	if region != "" && reqData.City != "" {
+		region += "," + reqData.City
+	} else {
+		region = reqData.City
+	}
+	saveData["region"] = strings.Split(region, ",")
+	//是否开启 正文 标题同时搜索只搜正文的开关
+	saveData["searchTypeSwitch"], _ = config.Sysconfig["searchTypeSwitch"].(bool)
 	//存入数据库
 	_id := mongodb.Save(dataexport.ExportTable, saveData)
 

+ 5 - 1
src/jfw/jyutil/jyutil.go

@@ -77,7 +77,7 @@ func Getopenid(code string) (openid string) {
 
 //
 func GetSessionVal(q map[string]interface{}) (*map[string]interface{}, map[string]interface{}) {
-	person, ok := public.MQFW.FindOneByField("user", q, `{"_id":1,"i_shareknow":1,"s_m_openid":1,"s_nickname":1,"s_headimage":1,"s_headimageurl":1,"s_phone":1,"s_m_phone":1,"l_registedate":1,"b_merge_remind":1,"i_ispush":1,"i_unlimited":1,"s_jyname":1}`)
+	person, ok := public.MQFW.FindOneByField("user", q, `{"_id":1,"i_shareknow":1,"s_m_openid":1,"s_nickname":1,"s_headimage":1,"s_headimageurl":1,"s_phone":1,"s_m_phone":1,"l_registedate":1,"b_merge_remind":1,"i_ispush":1,"i_unlimited":1,"s_jyname":1,"base_user_id":1}`)
 	sessionVal := make(map[string]interface{})
 	if !ok || person == nil || len(*person) == 0 {
 		return nil, sessionVal
@@ -111,6 +111,10 @@ func GetSessionVal(q map[string]interface{}) (*map[string]interface{}, map[strin
 	}
 	sessionVal["phone"] = phone
 	sessionVal["i_unlimited"] = util.IntAll((*person)["i_unlimited"])
+	base_uid := util.IntAllDef((*person)["base_user_id"], 0)
+	if base_uid != 0 {
+		sessionVal["base_user_id"] = base_uid //用户中台的uid
+	}
 	return person, sessionVal
 }
 

+ 43 - 0
src/jfw/modules/app/src/app/filter/baseuserfilter.go

@@ -0,0 +1,43 @@
+package filter
+
+import (
+	"jfw/config"
+	"jfw/public"
+	"log"
+	"net/http"
+	"qfw/util"
+
+	"github.com/go-xweb/httpsession"
+)
+
+type baseUserFilter struct {
+	W          http.ResponseWriter
+	R          *http.Request
+	Session    *httpsession.Session
+	GetSession map[string]interface{}
+}
+
+//判断session中是否存在base_user_id 不存在则更新
+
+func (this *baseUserFilter) Do() bool {
+	if flag, _ := config.Sysconfig["baseUserFilterFlag"].(bool); !flag {
+		return true
+	}
+	if this.R.Method == "POST" {
+		return true
+	}
+	if uid := this.GetSession["userId"]; uid != nil && uid != "" {
+		base_user_id := this.GetSession["base_user_id"]
+		if base_user_id == nil || base_user_id == 0 {
+			data, ok := public.MQFW.FindById("user", util.ObjToString(uid), `{"base_user_id":1}`)
+			if data != nil && ok && len(*data) > 0 {
+				if base_user_id := util.Int64All((*data)["base_user_id"]); base_user_id > 0 {
+					this.Session.Set("base_user_id", (*data)["base_user_id"])
+				} else {
+					log.Printf("%s用户暂无base_user_id", uid)
+				}
+			}
+		}
+	}
+	return true
+}

+ 3 - 0
src/jfw/modules/app/src/app/filter/filter.go

@@ -48,5 +48,8 @@ func (f *Filter) Do(w http.ResponseWriter, r *http.Request) bool {
 	if !(&phoneFilter{w, r, session, getSession}).Do() {
 		return false
 	}
+	if !(&baseUserFilter{w, r, session, getSession}).Do() {
+		return false
+	}
 	return true
 }

+ 58 - 5
src/jfw/modules/app/src/app/front/login.go

@@ -13,6 +13,7 @@ import (
 	"qfw/util/jy"
 	"qfw/util/redis"
 	qrpc "qfw/util/rpc"
+	"qfw/util/usercenter"
 	"regexp"
 	"strings"
 	"sync"
@@ -180,7 +181,7 @@ func (l *Login) Login() error {
 				deviceId := l.GetString("deviceId")
 				if user == nil || len(user) == 0 {
 					client := l.Header("User-Agent")
-					log.Println("client:", client)
+					log.Println(client)
 					//clearRidByRid(rid)
 					data := map[string]interface{}{
 						"i_appid":       2,
@@ -202,6 +203,15 @@ func (l *Login) Login() error {
 					data["s_regsource"] = isAndroidOrIOS(l.Header("User-Agent"))
 					_id := mongodb.Save("user", data)
 					if _id != "" {
+						//用户中台同步
+						func(userid string) {
+							formdata := map[string]interface{}{
+								"appid": "10000",
+								"phone": phone,
+							}
+							ck, _ := l.GetCookie("SESSIONID")
+							usercenter.AddBaseUser(mongodb, qutil.ObjToString(config.Sysconfig["userCenterApi"]), userid, formdata, ck)
+						}(_id)
 						jy.ClearPhoneIdentSession(l.Session())
 						returnSign = afterLogin(data, l.Session(), rid, oid, phoneType, channel, deviceId, true, l.ResponseWriter)
 						addr, _ := config.Sysconfig["nsq"].(string)
@@ -442,6 +452,11 @@ func (l *Login) Register() error {
 						"$unset": map[string]interface{}{"s_m_phone": ""},
 					}, false, false)
 					data["_id"] = wxuid
+					//用户中台同步
+					func(userid string) {
+						ck, _ := l.GetCookie("SESSIONID")
+						usercenter.UpdateBaseUser(mongodb, qutil.ObjToString(config.Sysconfig["userCenterApi"]), userid, ck)
+					}(qutil.ObjToString(wxuid))
 				} else {
 					data["i_appid"] = 2
 					data["l_registedate"] = time.Now().Unix()
@@ -457,6 +472,17 @@ func (l *Login) Register() error {
 					saveSuccess = saveid != ""
 				}
 				if saveSuccess && saveid != "" {
+					//用户中台同步
+					func(userid string) {
+						formdata := map[string]interface{}{
+							"appid":    "10000",
+							"phone":    phone,
+							"password": qutil.GetMd5String(password),
+							"company":  s_entname,
+						}
+						ck, _ := l.GetCookie("SESSIONID")
+						usercenter.AddBaseUser(mongodb, qutil.ObjToString(config.Sysconfig["userCenterApi"]), userid, formdata, ck)
+					}(saveid)
 					addr := config.Sysconfig["nsq"].(string)
 					topic := config.Sysconfig["nsq_topic"].(string)
 					go func() {
@@ -570,9 +596,14 @@ func (l *Login) WxLogin() {
 			if qutil.ObjToString((*user)["s_nickname"]) == "" && qutil.ObjToString((*user)["s_jyname"]) == "" {
 				upSet["s_jyname"] = jy.GetUserName("newother", config.Sysconfig["namePrefix"].(string))
 			}
-			go mongodb.UpdateById("user", BsonIdToSId((*user)["_id"]), map[string]interface{}{
-				"$set": upSet,
-			})
+			go func(userid string) {
+				mongodb.UpdateById("user", BsonIdToSId((*user)["_id"]), map[string]interface{}{
+					"$set": upSet,
+				})
+				ck, _ := l.GetCookie("SESSIONID")
+				usercenter.UpdateBaseUser(mongodb, qutil.ObjToString(config.Sysconfig["userCenterApi"]), userid, ck)
+			}(BsonIdToSId((*user)["_id"]))
+
 			returnSign = afterLogin(*user, l.Session(), rid, oid, phoneType, channel, deviceId, false, l.ResponseWriter)
 			return 1
 		} else {
@@ -604,6 +635,18 @@ func (l *Login) WxLogin() {
 			}
 			newUser["s_regsource"] = isAndroidOrIOS(l.Header("User-Agent")) //用户注册终端 ios 安卓 pc
 			if _id := mongodb.Save("user", newUser); _id != "" {
+				//用户中台同步
+				func(userid string) {
+					formdata := map[string]interface{}{
+						"appid":    "10000",
+						"nickname": qutil.If(u.Nickname == "", newUser["s_jyname"], u.Nickname),
+						"headimg":  u.HeadImageUrl,
+						"a_openid": u.OpenId,
+						"unionid":  u.UnionId,
+					}
+					ck, _ := l.GetCookie("SESSIONID")
+					usercenter.AddBaseUser(mongodb, qutil.ObjToString(config.Sysconfig["userCenterApi"]), userid, formdata, ck)
+				}(_id)
 				returnSign = afterLogin(newUser, l.Session(), rid, oid, phoneType, channel, deviceId, true, l.ResponseWriter)
 				if disWord != "" {
 					redisDis := redis.GetStr("other", "DIS_"+disWord[1:])
@@ -705,6 +748,10 @@ func (l *Login) ForgetPwd() error {
 				}}, false, false) {
 				l.DelSession("forgetPwdStep")
 				jy.ClearPhoneIdentSession(l.Session())
+				func(userid string) {
+					ck, _ := l.GetCookie("SESSIONID")
+					usercenter.UpdateBaseUser(mongodb, qutil.ObjToString(config.Sysconfig["userCenterApi"]), userid, ck)
+				}(BsonIdToSId(user["_id"]))
 				return "y"
 			}
 			return "saveError"
@@ -911,7 +958,7 @@ func createSession(s *httpsession.Session, person map[string]interface{}, loginI
 		default:
 			return false
 		}
-		field := `{"s_m_openid":1,"s_phone":1,"s_jpushid":1,"s_opushid":1,"s_appponetype":1,"s_headimageurl":1,"s_phone":1,"s_nickname":1,"s_appversion":1,"i_unlimited":1,"s_jyname":1}`
+		field := `{"s_m_openid":1,"s_phone":1,"s_jpushid":1,"s_opushid":1,"s_appponetype":1,"s_headimageurl":1,"s_phone":1,"s_nickname":1,"s_appversion":1,"i_unlimited":1,"s_jyname":1,"base_user_id":1}`
 		data, ok := mongodb.FindOneByField("user", query, field)
 		if !ok {
 			return false
@@ -939,6 +986,9 @@ func createSession(s *httpsession.Session, person map[string]interface{}, loginI
 	s.Set("s_appversion", person["s_appversion"])
 	s.Set("s_headimageurl", strings.Replace(qutil.ObjToString(person["s_headimageurl"]), "http://", "https://", 1))
 	s.Set("i_unlimited", qutil.IntAll(person["i_unlimited"]))
+	if base_userid := qutil.IntAllDef(person["base_user_id"], 0); base_userid != 0 {
+		s.Set("base_user_id", base_userid)
+	}
 	if qutil.ObjToString(person["s_phone"]) != "" {
 		phone := person["s_phone"].(string)
 		s.Set("s_phone", phone)
@@ -1011,6 +1061,9 @@ func ClearSession(s *httpsession.Session) {
 	s.Del("phone")
 	s.Del("i_unlimited")
 	s.Del("s_jyname")
+	s.Del("base_user_id")
+	s.Del("user")
+	s.Del("nickname")
 }
 
 //生成签名,返回手机端

+ 10 - 2
src/jfw/modules/app/src/app/front/logoffuser.go

@@ -2,9 +2,12 @@ package front
 
 import (
 	. "api"
+	"jfw/config"
 	"jfw/public"
 	"log"
+	"net/http"
 	qutil "qfw/util"
+	"qfw/util/usercenter"
 	"time"
 
 	"github.com/go-xweb/xweb"
@@ -118,11 +121,16 @@ func LogOffAppUser(user_id, cause string) bool {
 		_id, _ := primitive.ObjectIDFromHex(user_id)
 		if mongodb.Del("user", map[string]interface{}{
 			"_id": _id,
-			// "_id": bson.ObjectIdHex(ok),
 		}) {
+			//删除用户中台
+			ck := &http.Cookie{}
+			base_userid_del := usercenter.GetBaseUserId(mongodb, user_id)
+			usercenter.PostUserCenter(qutil.ObjToString(config.Sysconfig["userCenterApi"])+usercenter.UserCenterDelete, usercenter.ContentType_Json, user_id, map[string]interface{}{
+				"appid": "10000",
+				"id":    base_userid_del,
+			}, ck)
 			return true
 		}
-		// return true
 	}
 	return false
 }

+ 4 - 0
src/jfw/modules/app/src/app/front/me.go

@@ -9,6 +9,7 @@ import (
 	qutil "qfw/util"
 	"qfw/util/jy"
 	"qfw/util/redis"
+	"qfw/util/usercenter"
 	"strings"
 	"time"
 
@@ -195,6 +196,9 @@ func (l *Me) Updatepwd() error {
 				"l_updatepwdtime": time.Now().Unix(), //增加修改密码时间
 			},
 		}) {
+			//调用用户中台
+			ck, _ := l.GetCookie("SESSIONID")
+			usercenter.UpdateBaseUser(mongodb, qutil.ObjToString(config.Sysconfig["userCenterApi"]), userid, ck)
 			return "y"
 		} else {
 			return "saveError"

+ 9 - 1
src/jfw/modules/app/src/app/front/ws_dataExport.go

@@ -359,7 +359,15 @@ func (wd *WsDataExport) SearchExport() error {
 	saveData["s_openid"] = openid
 	saveData["s_userid"] = userId
 	saveData["comeinfrom"] = "supersearchPage"
-
+	region := util.If(reqData.Area == "全国", "", reqData.Area).(string)
+	if region != "" && reqData.City != "" {
+		region += "," + reqData.City
+	} else {
+		region = reqData.City
+	}
+	saveData["region"] = strings.Split(region, ",")
+	//是否开启 正文 标题同时搜索只搜正文的开关
+	saveData["searchTypeSwitch"], _ = config.Sysconfig["searchTypeSwitch"].(bool)
 	//存入数据库
 	_id := mongodb.Save(dataexport.ExportTable, saveData)
 

+ 4 - 1
src/jfw/modules/app/src/config.json

@@ -163,5 +163,8 @@
     "criticality":2,
     "canReadNotice": 3,
     "namePrefix":"JY_%s",
-    "smsServiceRpc":"127.0.0.1:932"
+    "smsServiceRpc":"127.0.0.1:932",
+    "searchTypeSwitch": true,
+    "baseUserFilterFlag":true,
+    "userCenterApi":"https://web-zxl.jydev.jianyu360.com"
 }

+ 12 - 1
src/jfw/modules/app/src/web/templates/big-member/header.html

@@ -1,8 +1,19 @@
 <!--S-header-->
+<style>
+  .jy-app-header .icon-back-white {
+    display: none;
+  }
+  .jy-app-header.transparent-header .icon-back-white {
+    display: inline-block;
+  }
+  .jy-app-header.transparent-header .icon-back {
+    display: none;
+  }
+</style>
 <div class="j-header jy-app-header border-line-b">
     <span class="header-left">
         <span class="icon-back j-icon base-icon"></span>
-        <!-- <span class="icon-back-white j-icon base-icon"></span> -->
+        <span class="icon-back-white j-icon base-icon"></span>
     </span>
     <span class="header-title"></span>
     <span class="header-right"></span>

+ 344 - 0
src/jfw/modules/app/src/web/templates/frontRouter/activity/sess/task-202207.html

@@ -0,0 +1,344 @@
+<!DOCTYPE html>
+<html lang="zh-CN" style="font-size: 50px;">
+
+<head>
+  <!-- <title>投标人专属免费计划</title> -->
+    <title>剑鱼超级会员节</title>
+    <!--引入公共资源头部-->
+    {{include "/big-member/meta.html"}}
+
+    <!--S-当前页面的css资源-->
+    <link rel="stylesheet" href=//cdn-common.jianyu360.com/cdn/lib/reset-css/5.0.1/reset.min.css />
+    <link rel="stylesheet" href=//cdn-common.jianyu360.com/cdn/lib/vant/2.12.24/lib/index.css />
+    <link rel="stylesheet" href=//cdn-common.jianyu360.com/cdn/lib/vant/2.12.24/lib/icon/local.css />
+    <link rel="stylesheet" href='{{Cdns .Host "seo" "cdn"|SafeUrl}}/common-module/active/2022.7/task-common.css?v={{Msg "seo" "version"}}' />
+    <link rel="stylesheet" href='{{Cdns .Host "seo" "cdn"|SafeUrl}}/common-module/active/2022.7/task-202207.css?v={{Msg "seo" "version"}}' />
+    <!--E-当前页面的css资源-->
+    <style>
+        .j-container.app > .j-main {
+            margin-top: -21.34vw;
+        }
+        /* @font-face {
+            font-family:"YouSheBiaoTiHei";
+            font-display: swap;
+            src:url('/big-member/image/new_big_index/font/YouSheBiaoTiHei-2.ttf');
+        } */
+        @font-face {
+            font-family:"YouSheBiaoTiHei";
+            font-display: swap;
+            src:url('/jyapp/fonts/YouSheBiaoTiHei-2.ttf');
+        }
+        .fixed-top {
+            top: 1.72rem;
+        }
+    </style>
+    <script>
+        try {
+            window.JyObj.hiddenBottom('0')
+        } catch (e) {
+            console.log('error: app not function')
+        }
+    </script>
+</head>
+
+<body>
+    <div class="j-container app">
+        {{include "/big-member/header.html"}}
+        <div class="j-main" id="main-app" v-cloak>
+            <div class="activity-rules-button" id="activity-rules-button" v-show="false" @click="dialogShow('rule', true)">规则</div>
+            <div class="header-banner">
+                <img class="header-banner-img" src="{{Cdns .Host "seo" "cdn"|SafeUrl}}/common-module/active/2022.7/header-banner.png" alt="">
+            </div>
+            <div class="content-container">
+                <!-- 预热 -->
+                <section class="section no-select section-yure" v-show="yureSectionShow">
+                    <div class="section-header">
+                        <div class="section-header-button">
+                            <img src="{{Cdns .Host "seo" "cdn"|SafeUrl}}/common-module/active/2022.7/title-yure@2x.png" alt="">
+                        </div>
+                    </div>
+                    <div class="section-content">
+                        <img src="{{Cdns .Host "seo" "cdn"|SafeUrl}}/common-module/active/2022.7/content-yure@2x.png" alt="">
+                        <div class="content-info">
+                            <div class="c-info-text" v-html="yureInfo.tipText"></div>
+                            <button
+                                class="c-info-button section-button button-small"
+                                @click="receiveYuReCoupon"
+                                :disabled="yureInfo.buttonDisabled"
+                                v-show="yureButtonShow"
+                                v-text="yureInfo.buttonText"></button>
+                        </div>
+                    </div>
+                </section>
+                <!-- 更多活动即将开启 -->
+                <div class="section no-select section-more-activities" v-show="yureSectionShow">
+                    <div class="section-header">
+                        <div class="header-text">
+                            <img src="{{Cdns .Host "seo" "cdn"|SafeUrl}}/common-module/active/2022.7/more-fuli-text@2x.png" alt="">
+                        </div>
+                    </div>
+                </div>
+                <!-- 福利一 -->
+                <div class="section no-select section-fuli1">
+                    <div class="section-header">
+                        <div class="section-header-button">
+                            <img src="{{Cdns .Host "seo" "cdn"|SafeUrl}}/common-module/active/2022.7/title-fuli1@2x.png" alt="">
+                        </div>
+                    </div>
+                    <div class="section-content coupon-list">
+                        <div
+                            v-for="item in couponList"
+                            :key="item.id"
+                            class="coupon-item">
+                            <div class="coupon-title">满<span v-text="item.Full"></span>可用</div>
+                            <div class="coupon-value"><span class="num" v-text="item.Reduce">50</span>元</div>
+                            <button class="section-button button-small" @click="receiveActiveCoupon([item])" v-text="receiveActiveButtonText(item)"></button>
+                            <div class="coupon-text" v-text="item.tipText"></div>
+                        </div>
+                    </div>
+                    <div class="section-footer">
+                        <button class="section-button button-middle" v-show="onKeyReceiveShow" :disabled="couponList.length === 0" @click="receiveActiveCoupon(couponList)">一键领取</button>
+                    </div>
+                </div>
+                <!-- 福利二 -->
+                <div class="section no-select section-fuli2 progress-section">
+                    <div class="section-header">
+                        <div class="section-header-button">
+                            <img src="{{Cdns .Host "seo" "cdn"|SafeUrl}}/common-module/active/2022.7/title-fuli2@2x.png" alt="">
+                        </div>
+                    </div>
+                    <div class="section-content mission-list" ref="missions">
+                        <img src="/common-module/active/2022.7/gift-box.png" alt="" class="mission-list-img">
+                        <div
+                            class="mission-list-item floating"
+                            :class="{ complete: item.complete, hide: item.hide, [item.id]: true, [item.className]: true }"
+                            v-for="item in missionsList"
+                            :id="'bubble-' + item.id"
+                            :style="{ left: item.x + 'rem', top: item.y + 'rem' }"
+                            @click="onClickReceive('mission', item)"
+                            :key="item.id">
+                            <div class="m-list-item-bg">
+                                <span class="num"><span class="num-add">+</span>${ item.num }</span>
+                                <span class="text" v-text="item.unit"></span>
+                                <span class="button" :id="'bubble-button--' + item.id">${ item.complete ? '点击领取' : '去完成' }</span>
+                            </div>
+                            <div class="m-list-item-text" v-text="item.name"></div>
+                        </div>
+                    </div>
+                    <div class="section-footer">
+                        <div class="progress-bar-container">
+                            <div class="progress-bar">
+                                <div
+                                    class="anchor"
+                                    v-for="a in progressAnchorList"
+                                    :key="a.rate"
+                                    :style="{ left: a.rate + '%' }"
+                                    :class="a.className">
+                                    <div class="anchor-text">${ a.anchorText }</div>
+                                    <div class="point-img" v-if="a.pointImg">
+                                        <img :src="progress.pointImgMap[a.pointImg]" alt="">
+                                    </div>
+                                    <div class="anchor-tip-text" v-show="a.tipText && false">
+                                        <p>免费领</p>
+                                        <p v-text="a.tipText"></p>
+                                    </div>
+                                </div>
+                                <div class="progress-bar-content" :style="{ width: rate + '%' }">
+                                    <div class="blink-point"></div>
+                                    <div class="blink-point-text anchor-text" v-show="blinkTextShow">${progress.current}剑鱼币</div>
+                                </div>
+                            </div>
+                        </div>
+                        <div class="progress-action-list">
+                            <button
+                                class="progress-action-button"
+                                :class="{ pointer: a.className === 'wait' }"
+                                :disabled="a.className === 'received'"
+                                v-for="(a, index) in progressAnchorList"
+                                v-if="a.tipText"
+                                :id="'progress-reward--' + a.id"
+                                @click="onClickReceive('schedule', a)"
+                                :key="index">${a.className === 'received' ? '已' : '免费'}领${a.tipText}</button>
+                        </div>
+                    </div>
+                </div>
+                <!-- 福利三 -->
+                <div class="section section-fuli3">
+                    <div class="section-header">
+                        <div class="section-header-button">
+                            <img src="{{Cdns .Host "seo" "cdn"|SafeUrl}}/common-module/active/2022.7/title-fuli3@2x.png" alt="">
+                        </div>
+                    </div>
+                    <div class="section-content entniche-card-list">
+                        <div class="entniche-card-item shangji"></div>
+                        <div class="entniche-card-item zhuanjia"></div>
+                    </div>
+                    <div class="section-footer">
+                        <div class="button-group">
+                            <button class="section-button learn-more" @click="toMemberPage">了解更多</button>
+                            <button class="section-button button-middle" @click="receiveFuli3">立即体验</button>
+                        </div>
+                        <div class="text">
+                            <p>满足企业多人使用 多场景赋能业务增长</p>
+                            <p>详情请致电咨询:400-108-6670</p>
+                        </div>
+                    </div>
+                </div>
+                <!-- 顶部悬浮 -->
+                <div class="fixed-top top-timeline" v-show="false">
+                    <div class="timeline-list">
+                        <div class="timeline-item yure" data-s-class="section-yure" v-show="activeState === 'waiting' || activeState === 'yureing'">
+                            <div class="t-left">预热福利</div>
+                            <div class="t-right">
+                                <div class="t-r-bottom">
+                                    <div class="t-r-b-l2" v-text="timeDuration.yure"></div>
+                                    <div class="t-r-b-r2" v-text="calcYuReTopText"></div>
+                                </div>
+                            </div>
+                        </div>
+                        <div class="timeline-item fuli1" data-s-class="section-fuli1">
+                            <div class="t-left">福利一</div>
+                            <div class="t-right">
+                                <div class="t-r-bottom" v-if="activeState === 'waiting' || activeState === 'yureing'">
+                                    <div class="t-r-b-l">距开始</div>
+                                    <div class="t-r-b-r" v-text="lastTimeText"></div>
+                                </div>
+                                <div class="t-r-bottom" v-else>
+                                    <div class="t-r-b-l2" v-text="timeDuration.active"></div>
+                                    <div class="t-r-b-r2" v-text="activeState === 'ended' ? '已结束' : '进行中'"></div>
+                                </div>
+                            </div>
+                        </div>
+                        <div class="timeline-item fuli2" data-s-class="section-fuli2">
+                            <div class="t-left">福利二</div>
+                            <div class="t-right">
+                                <div class="t-r-bottom" v-if="activeState === 'waiting' || activeState === 'yureing'">
+                                    <div class="t-r-b-l">距开始</div>
+                                    <div class="t-r-b-r" v-text="lastTimeText"></div>
+                                </div>
+                                <div class="t-r-bottom" v-else>
+                                    <div class="t-r-b-l2" v-text="timeDuration.active"></div>
+                                    <div class="t-r-b-r2" v-text="activeState === 'ended' ? '已结束' : '进行中'"></div>
+                                </div>
+                            </div>
+                        </div>
+                        <div class="timeline-item fuli3" data-s-class="section-fuli3">
+                            <div class="t-left">福利三</div>
+                            <div class="t-right">
+                                <div class="t-r-bottom" v-if="activeState === 'waiting' || activeState === 'yureing'">
+                                    <div class="t-r-b-l">距开始</div>
+                                    <div class="t-r-b-r" v-text="lastTimeText"></div>
+                                </div>
+                                <div class="t-r-bottom" v-else>
+                                    <div class="t-r-b-l2" v-text="timeDuration.active"></div>
+                                    <div class="t-r-b-r2" v-text="activeState === 'ended' ? '已结束' : '进行中'"></div>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+                <!-- 右侧悬浮 -->
+                <div class="fixed-right">
+                    <button class="fixed-action-button" @click="dialogShow('rule', true)">活动<br />规则</button>
+                    <button class="fixed-action-button" @click="dialog.myReward = true">我的<br />奖励</button>
+                </div>
+            </div>
+            <!-- 我的奖励 -->
+            <van-popup
+                v-model="dialog.myReward"
+                closeable
+                position="bottom"
+                class="reward-section"
+                round
+                get-container="body"
+                :style="{ maxHeight: '60%' }">
+                <section class="reward-card-container j-container no-select">
+                    <div class="r-header text-gradient-red"><div class="text-gradient-red">我的奖励</div></div>
+                    <div class="reward-card j-main section-card">
+                        <div class="reward-list" :class="{ empty: rewardList.length === 0 }">
+                            <div
+                                class="reward-list-item"
+                                v-for="item in rewardList"
+                                @click="onClickListItem(item)"
+                                :key="item.id">
+                                <span class="r-l-i-l j-icon-bg" :class="'icon-bg-' + item.icon"></span>
+                                <div class="r-l-i-c">
+                                    <div class="r-l-i-c-t">
+                                        <span class="reward-text" v-text="item.rewardText"></span>
+                                        <div class="receive-from" v-text="item.receiveFrom"></div>
+                                    </div>
+                                    <div class="receive-time" v-text="item.receiveTime"></div>
+                                </div>
+                                <div class="r-l-i-action">
+                                    <van-icon name="arrow"></van-icon>
+                                </div>
+                            </div>
+                            <div class="reward-empty" v-if="rewardList.length === 0">暂未获得奖励,快去完成任务吧</div>
+                        </div>
+                    </div>
+                </section>
+            </van-popup>
+            <!--S-弹窗-->
+            <van-popup id="active-tip-modal" v-model="dialog.show" :data-modal-type="dialog.type" :close-on-click-overlay="dialog.type !== 'over'">
+              <div v-show="dialog.type === 'rule'" class="modal-dialog active-tip--rule" :class="{max: getScreenMax}">
+                <h5 class="text-gradient-red">活动规则</h5>
+                <div class="rule-content">
+                  <div
+                    class="rule-item"
+                    v-for="(item, index) in rulesList"
+                    :key="index">
+                    <div class="rule-index">${ index + 1 }.</div>
+                    <div class="rule-text">${ item.text }</div>
+                  </div>
+                </div>
+                <button @click="dialogShow('rule', false)" id="dialog-button--rule">我知道了</button>
+                <img class="bg-image" src='{{Cdns .Host "seo" "cdn"|SafeUrl}}/common-module/active/2022.7/dialog-bg-big@2x.png?v={{Msg "seo" "version"}}' alt="扫一扫">
+              </div>
+              <div v-show="dialog.type === 'over'" class="modal-dialog active-tip--over">
+                <div class="close-dialog-icon" @click="dialog.show = false" id="dialog-icon--over" v-if="!forbidClose">
+                  <img src='{{Cdns .Host "seo" "cdn"|SafeUrl}}/common-module/active/2022.5.20/close.png?v={{Msg "seo" "version"}}' alt="x">
+                </div>
+                <h4>活动结束提醒</h4>
+                <img width="148" src='{{Cdns .Host "seo" "cdn"|SafeUrl}}/common-module/active/2022.5.20/empty.png?v={{Msg "seo" "version"}}' alt="活动已结束">
+                <p>
+                  对不起,该活动已结束
+                  <br>
+                  可前往参加“邀请领好礼活动
+                </p>
+                <button @click="onClickReceive('', { id: 'invite' })" id="dialog-button--over">立即前往</button>
+              </div>
+              <div v-show="dialog.type === 'success'" class="modal-dialog active-tip--success">
+                <h5 class="text-gradient-red">领取成功</h5>
+                <p>
+                  恭喜成功领取<i style="font-weight: bold">${dialog.giftMonth}个月</i>超级订阅
+                  <br>
+                  <span>可在“我的奖励”中查看</span>
+                </p>
+                <button @click="dialogShow('success', false)" id="dialog-button--success">我知道了</button>
+                <img class="bg-image" src='{{Cdns .Host "seo" "cdn"|SafeUrl}}/common-module/active/2022.7/dialog-bg@2x.png?v={{Msg "seo" "version"}}' alt="领取成功">
+              </div>
+            </van-popup>
+            <!--E-弹窗-->
+        </div>
+    </div>
+
+    <script src=//cdn-common.jianyu360.com/cdn/lib/vue/2.6.11/vue.min.js> </script>
+    <script src=//cdn-common.jianyu360.com/cdn/lib/vant/2.12.24/lib/vant.min.js> </script>
+    <script src=//cdn-common.jianyu360.com/cdn/lib/jquery/3.6.0/jquery.min.js> </script>
+    <script src=//cdn-common.jianyu360.com/cdn/lib/moment/2.29.1/min/moment.min.js></script>
+    {{include "/big-member/commonjs.html"}}
+    <script src='{{Cdns .Host "seo" "cdn"|SafeUrl}}/jyapp/js/common.js?v={{Msg "seo" "version"}}'></script>
+    <script>
+        $(function () {
+            var header = $('.j-header.jy-app-header')
+            header.addClass('transparent-header')
+                .find('.header-right')
+                .addClass('glyphicon-share')
+        })
+    </script>
+    <script src='{{Cdns .Host "seo" "cdn"|SafeUrl}}/common-module/public/js/van-share.js?v={{Msg "seo" "version"}}'></script>
+    <script src='{{Cdns .Host "seo" "cdn"|SafeUrl}}/common-module/active/2022.7/task-202207.js?v={{Msg "seo" "version"}}'></script>
+    {{include "/common/baiducc.html"}}
+</body>
+
+</html>

+ 0 - 2
src/jfw/modules/app/src/web/templates/frontRouter/activity/sess/task.html

@@ -190,8 +190,6 @@
             $('.j-header.jy-app-header')
                 .addClass('transparent-header')
                 .find('.header-left .j-icon')
-                .removeClass('icon-back')
-                .addClass('icon-back-white')
         })
     </script>
     <script src='{{Cdns .Host "seo" "cdn"|SafeUrl}}/common-module/active/2022.5.20/task.js?v={{Msg "seo" "version"}}'></script>

+ 1 - 1
src/jfw/modules/app/src/web/templates/weixin/historypush.html

@@ -399,7 +399,7 @@
                                                 </span>
                                             </template>
                                         </van-cell>
-                                        <van-cell center style="display: none; height: auto;"  @click="moreFiltersItemShow('fileItem', '附件')">
+                                        <van-cell center style="height: auto;"  @click="moreFiltersItemShow('fileItem', '附件')">
                                           <template #title>
                                               <span v-if="screenShow" class="noticeText">附件</span>
                                               <span v-else class="rootstyletitle">

+ 50 - 29
src/jfw/modules/common/src/qfw/util/bidsearch/search.go

@@ -35,7 +35,7 @@ const (
 )
 
 //GetWxsearchlistData 移动端招标信息搜索
-func GetWxsearchlistData(keywords, scope, city, publishtime, subtype, industry, minprice, maxprice, winner, buyerclass, hasBuyerTel, hasWinnerTel, fileExists string, pageNum, pageSize int, selectTypeArr []string, field, notkey string) (list *[]map[string]interface{}, b_word, a_word, s_word string) {
+func GetWxsearchlistData(keywords, scope, city, publishtime, subtype, industry, minprice, maxprice, winner, buyerclass, hasBuyerTel, hasWinnerTel, fileExists string, pageNum, pageSize int, selectTypeArr []string, field, notkey string, searchTypeSwitch bool) (list *[]map[string]interface{}, b_word, a_word, s_word string) {
 	var hightlightContent bool = false //是否高亮正文
 	for _, v := range selectTypeArr {
 		if v == "detail" {
@@ -53,7 +53,7 @@ func GetWxsearchlistData(keywords, scope, city, publishtime, subtype, industry,
 	} else {
 		findfields = fmt.Sprintf(`"%s"`, strings.Join(selectTypeArr, "\",\""))
 	}
-	qstr := GetSearchQuery(s_word, industry, minprice, maxprice, hasBuyerTel, hasWinnerTel, fileExists, findfields, GetBidSearchQuery(scope, city, publishtime, subtype, winner, buyerclass), notkey)
+	qstr := GetSearchQuery(s_word, industry, minprice, maxprice, hasBuyerTel, hasWinnerTel, fileExists, findfields, GetBidSearchQuery(scope, city, publishtime, subtype, winner, buyerclass), notkey, searchTypeSwitch)
 	if hightlightContent { //全文搜索
 		list = elastic.GetAllByNgram(INDEX, TYPE, qstr, `"detail"`, bidSearch_sort, field, (pageNum-1)*pageSize, pageSize, 100, true)
 	} else { //标题搜索
@@ -69,7 +69,7 @@ func GetWxsearchlistData(keywords, scope, city, publishtime, subtype, industry,
 }
 
 //GetPcBidSearchData pc端招标信息搜索
-func GetPcBidSearchData(searchvalue, area, city, publishtime, subtype, industry, minprice, maxprice, winner, buyerclass, hasBuyerTel, hasWinnerTel, fileExists string, start, pageSize int, isGetCount bool, selectTypeArr []string, field, notkey string, ispayed bool) (count, totalPage int64, list *[]map[string]interface{}) {
+func GetPcBidSearchData(searchvalue, area, city, publishtime, subtype, industry, minprice, maxprice, winner, buyerclass, hasBuyerTel, hasWinnerTel, fileExists string, start, pageSize int, isGetCount bool, selectTypeArr []string, field, notkey string, ispayed, searchTypeSwitch bool) (count, totalPage int64, list *[]map[string]interface{}) {
 	var findfields string
 	var hightlightContent bool = false //是否高亮正文
 	for _, v := range selectTypeArr {
@@ -83,11 +83,10 @@ func GetPcBidSearchData(searchvalue, area, city, publishtime, subtype, industry,
 	} else {
 		findfields = fmt.Sprintf(`"%s"`, strings.Join(selectTypeArr, "\",\""))
 	}
-	qstr := GetSearchQuery(searchvalue, industry, minprice, maxprice, hasBuyerTel, hasWinnerTel, fileExists, findfields, GetBidSearchQuery(area, city, publishtime, subtype, winner, buyerclass), notkey)
+	qstr := GetSearchQuery(searchvalue, industry, minprice, maxprice, hasBuyerTel, hasWinnerTel, fileExists, findfields, GetBidSearchQuery(area, city, publishtime, subtype, winner, buyerclass), notkey, searchTypeSwitch)
 	if isGetCount && qstr != "" && start == 0 {
 		count = elastic.Count(INDEX, TYPE, qstr)
 	}
-	log.Println("field:", field)
 	if !isGetCount || count > 0 || start > 0 {
 		var repl *[]map[string]interface{}
 		if hightlightContent {
@@ -238,27 +237,55 @@ func GetBidSearchQuery(area, city, publishtime, subtype, winner, buyerclass stri
 	return query
 }
 
-func GetSearchQuery(keyword, industry, minprice, maxprice, hasBuyerTel, hasWinnerTel, fileExists, findfields, mustquery, notkey string) (qstr string) {
+//包含正文或 附件 不包含标题
+func DetailFileORTitle(findfields string) bool {
+	return (strings.Contains(findfields, `"detail"`) || strings.Contains(findfields, `"filetext"`)) && !strings.Contains(findfields, `"title"`)
+}
+
+//包含标题和正文
+func DetailTitle(findfields string) bool {
+	return strings.Contains(findfields, `"detail"`) && strings.Contains(findfields, `"title"`)
+}
+func GetSearchQuery(keyword, industry, minprice, maxprice, hasBuyerTel, hasWinnerTel, fileExists, findfields, mustquery, notkey string, searchTypeSwitch bool) (qstr string) {
 	multi_match := `{"multi_match": {"query": "%s","type": "phrase", "fields": [%s]}}`
 	query := `{"query":{"bool":{"must":[%s],"must_not":[%s]}}}`
 	query_bool_should := `{"bool":{"should":[%s],"minimum_should_match": 1}}`
 	query_bools_must := `{"bool":{"must":[{"range":{"bidamount":{%s}}}]}},{"bool":{"must":[{"range":{"budget":{%s}}}],"must_not":[{"range":{"bidamount":{"gte":-1}}}]}}`
 	query_bool_must := `{"bool":{"must":[{"terms":{"s_subscopeclass":[%s]}}]}}`
 	query_missing := `{"constant_score":{"filter":{"missing":{"field":"%s"}}}}`
+	query_bool_must_term := `{"bool": {"must": [{ "term": {"isValidFile": %d }}]}}`
 	gte := `"gte": %s`
 	lte := `"lte": %s`
 	musts, must_not := []string{}, []string{}
 	if mustquery != "" {
 		musts = append(musts, mustquery)
 	}
-
 	//搜索范围是否只有附件
 	//搜索范围只选择附件,是否有附件条件无效;
-	var isFileSearch bool = findfields == "filetext"
+	var isFileSearch bool = findfields == `"filetext"`
 	if keyword != "" {
 		keyword_multi_match := fmt.Sprintf(multi_match, "%s", findfields)
 		shoulds := []string{}
 		for _, v := range strings.Split(keyword, "+") {
+			if elastic.ReplaceYH(v) == "" {
+				continue
+			}
+			if len([]rune(elastic.ReplaceYH(v))) == 1 {
+				//单个字 搜索范围 有全文或者附件 无标题 例如:学 虚拟机 detail  搜索的时候加上标题
+				if DetailFileORTitle(findfields) {
+					keyword_multi_match = fmt.Sprintf(multi_match, "%s", findfields+`,"title"`)
+				}
+			} else {
+				//标题+全文搜索 搜索类型开关打开 默认搜索全文;(全文包含标题)(单字排除)
+				if searchTypeSwitch && DetailTitle(findfields) {
+					if strings.Contains(findfields, `"title",`) {
+						findfields = strings.Replace(findfields, `"title",`, ``, -1)
+					} else if strings.Contains(findfields, `,"title"`) {
+						findfields = strings.Replace(findfields, `,"title"`, ``, -1)
+					}
+					keyword_multi_match = fmt.Sprintf(multi_match, "%s", findfields)
+				}
+			}
 			shoulds = append(shoulds, fmt.Sprintf(keyword_multi_match, elastic.ReplaceYH(v)))
 		}
 		musts = append(musts, fmt.Sprintf(elastic.NgramMust, strings.Join(shoulds, ",")))
@@ -319,15 +346,22 @@ func GetSearchQuery(keyword, industry, minprice, maxprice, hasBuyerTel, hasWinne
 			if v == "" {
 				continue
 			}
+			if len([]rune(elastic.ReplaceYH(v))) == 1 {
+				//单个字 搜索范围 有全文或者附件 无标题 例如:学 虚拟机 detail  搜索的时候加上标题
+				if DetailFileORTitle(findfields) {
+					notkey_multi_match = fmt.Sprintf(multi_match, "%s", findfields+`,"title"`)
+				}
+			}
 			notkey_must_not = append(notkey_must_not, fmt.Sprintf(notkey_multi_match, elastic.ReplaceYH(v)))
 		}
 		must_not = append(must_not, fmt.Sprintf(query_bool_should, strings.Join(notkey_must_not, ",")))
 	}
 	if !isFileSearch && fileExists != "" {
 		if fileExists == "1" { //有附件
-			must_not = append(must_not, fmt.Sprintf(query_missing, "filetext"))
+			must_not = append(must_not, fmt.Sprintf(query_missing, "isValidFile"))
+			musts = append(musts, fmt.Sprintf(query_bool_must_term, 1))
 		} else if fileExists == "-1" { //无附件
-			musts = append(musts, fmt.Sprintf(query_missing, "filetext"))
+			musts = append(musts, fmt.Sprintf(query_missing, "isValidFile"))
 		}
 	}
 	qstr = fmt.Sprintf(query, strings.Join(musts, ","), strings.Join(must_not, ","))
@@ -368,12 +402,12 @@ func PublicSearch(userId, selectType, publishtime string, bidSearchOldUserLimit
 }
 
 //所有的再次分词查询 只查标题
-func IntegratedData(platform string, s_word, secondKWS, industry, minprice, maxprice, hasBuyerTel, hasWinnerTel, fileExists, secondFlag, area, city, publishtime, subtype, buyerclass, notkey string, queryItems []string, list *[]map[string]interface{}, field string) (string, string, string, string, *[]map[string]interface{}) {
+func IntegratedData(platform string, s_word, secondKWS, industry, minprice, maxprice, hasBuyerTel, hasWinnerTel, fileExists, secondFlag, area, city, publishtime, subtype, buyerclass, notkey string, queryItems []string, list *[]map[string]interface{}, field string, searchTypeSwitch bool) (string, string, string, string, *[]map[string]interface{}) {
 	var pcAjaxFlag string
 	var secRel *[]map[string]interface{} = list
 	if secondKWS = jy.HttpEs(s_word, "ik_smart", public.DbConf.Elasticsearch.Main.Address); secondKWS != "" {
 		findfields := `"title"`
-		qstr := GetSearchQuery(secondKWS, industry, minprice, maxprice, hasBuyerTel, hasWinnerTel, fileExists, findfields, GetBidSearchQuery(area, city, publishtime, subtype, "", buyerclass), notkey)
+		qstr := GetSearchQuery(secondKWS, industry, minprice, maxprice, hasBuyerTel, hasWinnerTel, fileExists, findfields, GetBidSearchQuery(area, city, publishtime, subtype, "", buyerclass), notkey, searchTypeSwitch)
 		secRel = elastic.GetAllByNgram(INDEX, TYPE, qstr, findfields, bidSearch_sort, field, 0, 2*SearchPageSize_PC, 0, false)
 		if secRel != nil && len(*secRel) > 0 {
 			public.BidListConvert(industry, secRel)
@@ -457,7 +491,7 @@ func LisetData(stype, pageNum int, list *[]map[string]interface{}, secondFlag st
 				}
 				v["detail"] = detail
 				v["href"] = util.EncodeArticleId2ByCheck(util.GetRandom(20))
-				if v["filetext"] != nil {
+				if isValidFile, _ := v["isValidFile"].(bool); isValidFile {
 					delete(v, "filetext")
 					v["fileExists"] = true
 				}
@@ -491,33 +525,20 @@ func LisetData(stype, pageNum int, list *[]map[string]interface{}, secondFlag st
 func SearchData(platform string, request *http.Request, currentPage int, userId, secondKWS, s_word, area, city, publishtime, subtype, industry, minprice, maxprice, winner, buyerclass, hasBuyerTel, hasWinnerTel, fileExists string, start, pageSize int, isGetCount bool, queryItems []string, field, notkey string, isPayedUser, searchTypeSwitch bool) (second, b_word, a_word, pcAjaxFlag, secondFlag string, count, totalPage int64, list *[]map[string]interface{}) {
 	//包含标题才能进行二次搜索
 	var secondSearch = strings.Contains(strings.Join(queryItems, ","), "title")
-	//标题 全文搜索 搜索类型开关打开 默认搜索全文;(全文包含标题)(单字排除)
-	if searchTypeSwitch {
-		findFields := strings.Join(queryItems, ",")
-		var switchBool = strings.Contains(findFields, "detail") && strings.Contains(findFields, "title")
-		if switchBool {
-			if strings.Contains(findFields, "title,") {
-				findFields = strings.Replace(findFields, "title,", "", -1)
-			} else if strings.Contains(findFields, `,title`) {
-				findFields = strings.Replace(findFields, ",title", "", -1)
-			}
-			queryItems = strings.Split(findFields, ",")
-		}
-	}
 	var searchvalue = s_word
 	number := util.If(platform == "app" || platform == "wx", 1, 0)
 	if platform == "app" || platform == "wx" {
-		list, b_word, a_word, s_word = GetWxsearchlistData(s_word, area, city, publishtime, subtype, industry, minprice, maxprice, winner, buyerclass, hasBuyerTel, hasWinnerTel, fileExists, start, SearchPageSize_APP, queryItems, field, notkey)
+		list, b_word, a_word, s_word = GetWxsearchlistData(s_word, area, city, publishtime, subtype, industry, minprice, maxprice, winner, buyerclass, hasBuyerTel, hasWinnerTel, fileExists, start, SearchPageSize_APP, queryItems, field, notkey, searchTypeSwitch)
 		if list != nil && len(*list) != 0 {
 			count = int64(len(*list))
 		}
 	} else {
-		count, totalPage, list = GetPcBidSearchData(s_word, area, city, publishtime, subtype, industry, minprice, maxprice, winner, buyerclass, hasBuyerTel, hasWinnerTel, fileExists, start, pageSize, isGetCount, queryItems, field, notkey, isPayedUser)
+		count, totalPage, list = GetPcBidSearchData(s_word, area, city, publishtime, subtype, industry, minprice, maxprice, winner, buyerclass, hasBuyerTel, hasWinnerTel, fileExists, start, pageSize, isGetCount, queryItems, field, notkey, isPayedUser, searchTypeSwitch)
 	}
 
 	if len([]rune(s_word)) > 3 && int(count) < SearchPageSize_PC && start == number && secondSearch {
 		var paramList = list
-		s_word, pcAjaxFlag, secondFlag, second, list = IntegratedData(platform, s_word, secondKWS, industry, minprice, maxprice, hasBuyerTel, hasWinnerTel, fileExists, secondFlag, area, city, publishtime, subtype, buyerclass, notkey, queryItems, paramList, field)
+		s_word, pcAjaxFlag, secondFlag, second, list = IntegratedData(platform, s_word, secondKWS, industry, minprice, maxprice, hasBuyerTel, hasWinnerTel, fileExists, secondFlag, area, city, publishtime, subtype, buyerclass, notkey, queryItems, paramList, field, searchTypeSwitch)
 	}
 
 	listSize := 0

+ 106 - 52
src/jfw/modules/common/src/qfw/util/dataexport/dataexport.go

@@ -28,27 +28,28 @@ type KeyWord struct {
 
 /*筛选条件*/
 type SieveCondition struct {
-	Id           string    `json:"id"`
-	PublishTime  string    `json:"publishtime"`  //发布时间
-	Area         []string  `json:"area"`         //地区-省份
-	City         []string  `json:"city"`         //地区-城市
-	Region       []string  `json:"region"`       //地区-省份+城市
-	Industry     []string  `json:"industry"`     //行业
-	Keyword      []KeyWord `json:"keywords"`     //关键词
-	Buyer        []string  `json:"buyer"`        //招标单位(采购单位)
-	Buyerclass   []string  `json:"buyerclass"`   //采购单位类型
-	HasBuyerTel  string    `json:"hasBuyertel"`  //是否有采购单位电话
-	Winner       []string  `json:"winner"`       //中标单位
-	HasWinnerTel string    `json:"hasWinnertel"` //是否有中标单位电话
-	ComeInTime   int64     `json:"comeintime"`   //入库时间(秒)
-	OpenId       string    `json:"openid"`       //用户openid
-	MinPrice     string    `json:"minprice"`     //金额——最少
-	MaxPrice     string    `json:"maxprice"`     //金额——最多
-	SelectType   string    `json:"selectType"`   //筛选(正文 or 标题)
-	Subtype      string    `json:"subtype"`      //信息类型
-	SelectIds    []string  `json:"selectId"`     //选择信息导出
-	Comeinfrom   string    `json:"comeinfrom"`   //查询来源
-	FileExists   string    `json:"fileExists"`   //是否有附件
+	Id               string    `json:"id"`
+	PublishTime      string    `json:"publishtime"`      //发布时间
+	Area             []string  `json:"area"`             //地区-省份
+	City             []string  `json:"city"`             //地区-城市
+	Region           []string  `json:"region"`           //地区-省份+城市
+	Industry         []string  `json:"industry"`         //行业
+	Keyword          []KeyWord `json:"keywords"`         //关键词
+	Buyer            []string  `json:"buyer"`            //招标单位(采购单位)
+	Buyerclass       []string  `json:"buyerclass"`       //采购单位类型
+	HasBuyerTel      string    `json:"hasBuyertel"`      //是否有采购单位电话
+	Winner           []string  `json:"winner"`           //中标单位
+	HasWinnerTel     string    `json:"hasWinnertel"`     //是否有中标单位电话
+	ComeInTime       int64     `json:"comeintime"`       //入库时间(秒)
+	OpenId           string    `json:"openid"`           //用户openid
+	MinPrice         string    `json:"minprice"`         //金额——最少
+	MaxPrice         string    `json:"maxprice"`         //金额——最多
+	SelectType       string    `json:"selectType"`       //筛选(正文 or 标题)
+	Subtype          string    `json:"subtype"`          //信息类型
+	SelectIds        []string  `json:"selectId"`         //选择信息导出
+	Comeinfrom       string    `json:"comeinfrom"`       //查询来源
+	FileExists       string    `json:"fileExists"`       //是否有附件
+	SearchTypeSwitch bool      `json:"searchTypeSwitch"` //是否开启 正文 标题同时搜索只搜正文的开关
 }
 
 const (
@@ -68,6 +69,18 @@ var topType = map[string]string{
 	"招标公告":   "招标",
 	"招标结果":   "结果",
 	"招标信用信息": "其它",
+	"拟建项目":   "拟建",
+	"采购意向":   "采购意向",
+}
+
+//包含正文或 附件 不包含标题
+func DetailFileORTitle(findfields string) bool {
+	return (strings.Contains(findfields, "detail") || strings.Contains(findfields, "filetext")) && !strings.Contains(findfields, "title")
+}
+
+//包含正文包含标题
+func DetailANDTitle(findfields string) bool {
+	return strings.Contains(findfields, "detail") && strings.Contains(findfields, "title")
 }
 
 //获取数据导出查询语句
@@ -84,6 +97,7 @@ func getDataExportSql(scd *SieveCondition) string {
 	query_bool_must := `{"terms":{"%s":[%s]}}`
 	query_bool_must_and := `{"bool":{"must":[%s]%s}}`
 	query_missing := `{"constant_score":{"filter":{"missing":{"field":"%s"}}}}`
+	query_bool_must_term := `{"bool": {"must": [{ "term": {"isValidFile": %d }}]}}`
 	gte := `"gte": %s`
 	lte := `"lte": %s`
 
@@ -223,18 +237,27 @@ func getDataExportSql(scd *SieveCondition) string {
 		}
 	}
 	boolsNum := 0
+	selectType := scd.SelectType
 	//should
 	if len(scd.Keyword) > 0 {
 		boolsNum = 1
 		queryItem := ""
-		if scd.SelectType == "" {
+		if selectType == "" {
 			queryItem = "title"
-		} else if scd.SelectType == "all" {
+		} else if selectType == "all" {
 			queryItem = "detail\", \"title"
 		} else {
-			queryItem = strings.ReplaceAll(scd.SelectType, ",", "\",\"")
+			if scd.SearchTypeSwitch && DetailANDTitle(selectType) {
+				if strings.Contains(selectType, "title,") {
+					selectType = strings.Replace(selectType, "title,", "", -1)
+				} else if strings.Contains(selectType, ",title") {
+					selectType = strings.Replace(selectType, ",title", "", -1)
+				}
+
+			}
+			queryItem = strings.ReplaceAll(selectType, ",", "\",\"")
 		}
-		multi_match = fmt.Sprintf(multi_match, "%s", "\""+queryItem+"\"")
+		multi_match_new := fmt.Sprintf(multi_match, "%s", "\""+queryItem+"\"")
 
 		if scd.Comeinfrom == "supersearchPage" {
 			var keywordArr []string
@@ -258,25 +281,53 @@ func getDataExportSql(scd *SieveCondition) string {
 			if v.Keyword != "" {
 				if strings.Contains(v.Keyword, "+") {
 					for _, vk := range strings.Split(v.Keyword, "+") {
-						shoulds = append(shoulds, fmt.Sprintf(multi_match, "\""+vk+"\""))
+						//单个字 搜索范围 有全文或者附件 无标题 例如:学 虚拟机 detail  搜索的时候加上标题
+						if scd.Comeinfrom == "supersearchPage" && DetailFileORTitle(selectType) && len([]rune(elastic.ReplaceYH(vk))) == 1 {
+							queryItem = strings.ReplaceAll(selectType+",title", ",", "\",\"")
+							shouldsKey := fmt.Sprintf(multi_match, "\""+vk+"\"", "\""+queryItem+"\"")
+							shoulds = append(shoulds, shouldsKey)
+						} else {
+							shoulds = append(shoulds, fmt.Sprintf(multi_match_new, "\""+vk+"\""))
+						}
 					}
 				} else if strings.Contains(v.Keyword, " ") {
 					for _, vk := range strings.Split(v.Keyword, " ") {
-						shoulds = append(shoulds, fmt.Sprintf(multi_match, "\""+vk+"\""))
+						//单个字 搜索范围 有全文或者附件 无标题 例如:学 虚拟机 detail  搜索的时候加上标题
+						if scd.Comeinfrom == "supersearchPage" && DetailFileORTitle(selectType) && len([]rune(elastic.ReplaceYH(vk))) == 1 {
+							queryItem = strings.ReplaceAll(selectType+",title", ",", "\",\"")
+							shouldsKey := fmt.Sprintf(multi_match, "\""+vk+"\"", "\""+queryItem+"\"")
+							shoulds = append(shoulds, shouldsKey)
+						} else {
+							shoulds = append(shoulds, fmt.Sprintf(multi_match_new, "\""+vk+"\""))
+						}
 					}
 				} else {
-					shoulds = append(shoulds, fmt.Sprintf(multi_match, "\""+v.Keyword+"\""))
+					//单个字 搜索范围 有全文或者附件 无标题 例如:学 虚拟机 detail  搜索的时候加上标题
+					if scd.Comeinfrom == "supersearchPage" && DetailFileORTitle(selectType) && len([]rune(elastic.ReplaceYH(v.Keyword))) == 1 {
+						queryItem = strings.ReplaceAll(selectType+",title", ",", "\",\"")
+						shouldsKey := fmt.Sprintf(multi_match, "\""+v.Keyword+"\"", "\""+queryItem+"\"")
+						shoulds = append(shoulds, shouldsKey)
+					} else {
+						shoulds = append(shoulds, fmt.Sprintf(multi_match_new, "\""+v.Keyword+"\""))
+					}
 				}
 			}
 
 			//附加词
 			for _, vv := range v.Appended {
-				shoulds = append(shoulds, fmt.Sprintf(multi_match, "\""+vv+"\""))
+				shoulds = append(shoulds, fmt.Sprintf(multi_match_new, "\""+vv+"\""))
 			}
 
 			//排除词
 			for _, vv := range v.Exclude {
-				must_not = append(must_not, fmt.Sprintf(multi_match, "\""+vv+"\""))
+				//单个字 搜索范围 有全文或者附件 无标题 例如:学 虚拟机 detail  搜索的时候加上标题
+				if scd.Comeinfrom == "supersearchPage" && DetailFileORTitle(selectType) && len([]rune(elastic.ReplaceYH(vv))) == 1 {
+					queryItem = strings.ReplaceAll(selectType+",title", ",", "\",\"")
+					shouldsKey := fmt.Sprintf(multi_match, "\""+vv+"\"", "\""+queryItem+"\"")
+					shoulds = append(shoulds, shouldsKey)
+				} else {
+					must_not = append(must_not, fmt.Sprintf(multi_match_new, "\""+vv+"\""))
+				}
 			}
 
 			//添加
@@ -306,12 +357,13 @@ func getDataExportSql(scd *SieveCondition) string {
 
 	//搜索范围是否只有附件
 	//搜索范围只选择附件,是否有附件条件无效;
-	var isFileSearch = strings.ReplaceAll(scd.SelectType, ",", "\",\"") == "filetext"
+	var isFileSearch = strings.ReplaceAll(selectType, ",", "\",\"") == "filetext"
 	if !isFileSearch && scd.FileExists != "" {
 		if scd.FileExists == "1" { //有附件
-			must_not = append(must_not, fmt.Sprintf(query_missing, "filetext"))
+			must_not = append(must_not, fmt.Sprintf(query_missing, "isValidFile"))
+			musts = append(musts, fmt.Sprintf(query_bool_must_term, 1))
 		} else if scd.FileExists == "-1" { //无附件
-			musts = append(musts, fmt.Sprintf(query_missing, "filetext"))
+			musts = append(musts, fmt.Sprintf(query_missing, "isValidFile"))
 		}
 	}
 	qstr := fmt.Sprintf(query, strings.Join(musts, ","), strings.Join(must_not, ","), strings.Join(bools, ","), boolsNum)
@@ -327,26 +379,28 @@ func GetSqlObjFromId(mongo mg.MongodbSim, _id string) *SieveCondition {
 	if query, ok = mongo.FindById(ExportTable, _id, nil); !ok {
 		return nil
 	}
+	searchTypeSwitch, _ := (*query)["searchTypeSwitch"].(bool)
 	return &SieveCondition{
-		Id:           _id,
-		Keyword:      getKeyWordArrFromDbResult((*query)["keywords"]),
-		Industry:     getStringArrFromDbResult((*query)["industry"]),
-		MinPrice:     qutil.ObjToString((*query)["minprice"]),
-		MaxPrice:     qutil.ObjToString((*query)["maxprice"]),
-		Subtype:      qutil.ObjToString((*query)["subtype"]),
-		Area:         getStringArrFromDbResult((*query)["area"]),
-		City:         getStringArrFromDbResult((*query)["city"]),
-		SelectType:   qutil.ObjToString((*query)["selectType"]),
-		PublishTime:  qutil.ObjToString((*query)["publishtime"]),
-		Buyer:        getStringArrFromDbResult((*query)["buyer"]),
-		Buyerclass:   getStringArrFromDbResult((*query)["buyerclass"]),
-		HasBuyerTel:  qutil.ObjToString((*query)["hasBuyertel"]),
-		Winner:       getStringArrFromDbResult((*query)["winner"]),
-		HasWinnerTel: qutil.ObjToString((*query)["hasWinnertel"]),
-		ComeInTime:   qutil.Int64All((*query)["comeintime"]),
-		Comeinfrom:   qutil.ObjToString((*query)["comeinfrom"]),
-		SelectIds:    getStringArrFromDbResult((*query)["selectIds"]),
-		FileExists:   qutil.ObjToString((*query)["fileExists"]),
+		Id:               _id,
+		Keyword:          getKeyWordArrFromDbResult((*query)["keywords"]),
+		Industry:         getStringArrFromDbResult((*query)["industry"]),
+		MinPrice:         qutil.ObjToString((*query)["minprice"]),
+		MaxPrice:         qutil.ObjToString((*query)["maxprice"]),
+		Subtype:          qutil.ObjToString((*query)["subtype"]),
+		Area:             getStringArrFromDbResult((*query)["area"]),
+		City:             getStringArrFromDbResult((*query)["city"]),
+		SelectType:       qutil.ObjToString((*query)["selectType"]),
+		PublishTime:      qutil.ObjToString((*query)["publishtime"]),
+		Buyer:            getStringArrFromDbResult((*query)["buyer"]),
+		Buyerclass:       getStringArrFromDbResult((*query)["buyerclass"]),
+		HasBuyerTel:      qutil.ObjToString((*query)["hasBuyertel"]),
+		Winner:           getStringArrFromDbResult((*query)["winner"]),
+		HasWinnerTel:     qutil.ObjToString((*query)["hasWinnertel"]),
+		ComeInTime:       qutil.Int64All((*query)["comeintime"]),
+		Comeinfrom:       qutil.ObjToString((*query)["comeinfrom"]),
+		SelectIds:        getStringArrFromDbResult((*query)["selectIds"]),
+		FileExists:       qutil.ObjToString((*query)["fileExists"]),
+		SearchTypeSwitch: searchTypeSwitch,
 	}
 }
 

+ 15 - 14
src/jfw/modules/common/src/qfw/util/jy/bigVipPower.go

@@ -88,22 +88,23 @@ func ClearBigVipUserPower(userId string) bool {
 	cacheKey := fmt.Sprintf(PowerCacheKey, userId)
 	return redis.Del(PowerCacheDb, cacheKey)
 }
+
 //获取商机管理个人基本信息
 func GetEntnicheState(userId string, mysql *mysql.Mysql, mg MongodbSim) *BigVipBaseMsg {
-    userPower := BigVipBaseMsg{}
-    userPower.EntnicheStatus = 0
-    //手机号
-    data, ok := mg.FindById("user", userId, `{"s_phone":1,"s_m_phone":1,i_member_status":1,"i_member_give":1,"s_member_mainid":1,"i_member_sub_status":1,"i_member_trial":1,"i_vip_status":1,"o_vipjy":1,"o_jy":1,"l_registedate":1}`)
-    if ok && *data != nil && len(*data) > 0 {
-        //查询是否是商机管理付费用户
-        phone, _ := qutil.If((*data)["s_phone"] != nil, (*data)["s_phone"], (*data)["s_m_phone"]).(string)
-        if phone != "" {
-            if count := mysql.CountBySql(`SELECT count(1) FROM entniche_user u LEFT JOIN entniche_info i ON u.ent_id=i.id WHERE u.phone=? and u.power=1 and i.status=1`, phone); count > 0 {
-                userPower.EntnicheStatus = 1
-            }
-        }
-    }
-    return &userPower
+	userPower := BigVipBaseMsg{}
+	userPower.EntnicheStatus = 0
+	//手机号
+	data, ok := mg.FindById("user", userId, `{"s_phone":1,"s_m_phone":1,i_member_status":1,"i_member_give":1,"s_member_mainid":1,"i_member_sub_status":1,"i_member_trial":1,"i_vip_status":1,"o_vipjy":1,"o_jy":1,"l_registedate":1}`)
+	if ok && *data != nil && len(*data) > 0 {
+		//查询是否是商机管理付费用户
+		phone, _ := qutil.If((*data)["s_phone"] != nil, (*data)["s_phone"], (*data)["s_m_phone"]).(string)
+		if phone != "" {
+			if count := mysql.CountBySql(`SELECT count(1) FROM entniche_user u LEFT JOIN entniche_info i ON u.ent_id=i.id WHERE u.phone=? and u.power=1 and i.status=1`, phone); count > 0 {
+				userPower.EntnicheStatus = 1
+			}
+		}
+	}
+	return &userPower
 }
 
 //获取大会员个人基本信息

+ 150 - 1
src/jfw/modules/common/src/qfw/util/jy/subscribepush.go

@@ -11,6 +11,7 @@ import (
 	"qfw/util/redis"
 	"strconv"
 	"strings"
+	"sync"
 	"time"
 
 	"go.mongodb.org/mongo-driver/bson/primitive"
@@ -586,7 +587,7 @@ func (s *subscribePush) GetInfoByIds(Mgo_bidding mg.MongodbSim, bidding, bidding
 	return array
 }
 
-//保存最近7天的数据到历史记录--普通用户
+//保存最近7天的数据到历史记录
 func (s *subscribePush) MakeHistoryDatas(MQFW mg.MongodbSim, PushMysql *mysql.Mysql, userId string, PushView func(userid, allquery, field string, pageNum, pageSize int) (keys []interface{}, list *[]map[string]interface{})) (bool, []*SubPushList) {
 	log.Println("匹配最近7天数据", userId)
 	field := `"_id","title","publishtime","toptype","subtype","type","area","city","s_subscopeclass","buyerclass","budget","bidamount","filetext","spidercode","site"`
@@ -841,3 +842,151 @@ func InfoFormats(info map[string]interface{}, tmp map[string]interface{}) map[st
 	info["type"] = infotype
 	return info
 }
+
+//保存最近7天的数据到历史记录--新
+/*已选条件--关键词*/
+type ViewKeyWord struct {
+	Keyword  []string `json:"key"`       //关键词
+	Appended []string `json:"appendkey"` //附加词
+	Exclude  []string `json:"notkey"`    //排除词
+	MatchWay int      `json:"matchway"`  //匹配模式
+}
+
+func (s *subscribePush) MakeHistoryDatasNew(PushMysql *mysql.Mysql, userId string, entId int, DefaultPushList func(userId, moduleFlag string, entId int) (keyword []byte, list *[]map[string]interface{}, deptId int)) (bool, []*SubPushList) {
+	log.Println(s.ModuleFlag, "匹配最近7天数据", userId, entId)
+	//
+	t1 := time.Now()
+	kw, list, deptId := DefaultPushList(userId, s.ModuleFlag, entId)
+	if list == nil || len(*list) == 0 {
+		return false, nil
+	}
+	var isNext = false
+	log.Println("es查询耗时:", time.Since(t1))
+	var resultList []*SubPushList
+	if list != nil && len(*list) > 0 {
+		keyword := []ViewKeyWord{}
+		if err := json.Unmarshal(kw, &keyword); err != nil {
+			return false, nil
+		}
+		//超过50条先处理50条 返回前50条
+		listOne := *list
+		if len(*list) > pageSize {
+			listOne = (*list)[:pageSize]
+		}
+		resultList = s.listManager(PushMysql, listOne, keyword, (len(listOne)+pageSize)/pageSize, entId, deptId, userId)
+		if len(*list) > pageSize {
+			isNext = true
+			listOther := (*list)[pageSize:]
+			go s.listManager(PushMysql, listOther, keyword, (len(listOther)+pageSize)/pageSize, entId, deptId, userId)
+		}
+	}
+	log.Println("第一批推送信息处理耗时:", time.Since(t1).Seconds(), len(resultList))
+	return isNext, resultList
+}
+
+//
+func (s *subscribePush) listManager(PushMysql *mysql.Mysql, list []map[string]interface{}, keyword []ViewKeyWord, ccount, entId, deptId int, userId string) (resultList []*SubPushList) {
+	t2 := time.Now()
+	now := time.Now()
+	var (
+		wg = &sync.WaitGroup{}
+		wc = make(chan bool, ccount)
+	)
+	for _, v := range list {
+		wg.Add(1)
+		wc <- true
+		go func(v map[string]interface{}) {
+			defer func() {
+				wg.Done()
+				<-wc
+			}()
+			redisKey := fmt.Sprintf("pushinfo_%s_%s", userId, ObjToString(v["_id"]))
+			title := strings.Replace(ObjToString(v["title"]), "\n", "", -1)
+			var myInsert = make(map[string]interface{})
+			myInsert["userid"] = userId
+			myInsert["infoid"] = ObjToString(v["_id"])
+			myInsert["date"] = now.Unix()
+			matchkeys := getKeys(title, keyword)
+			myInsert["matchkeys"] = strings.Join(matchkeys, " ")
+			if v["area"] != nil {
+				myInsert["area"] = If(ObjToString(v["area"]) == "A", 0, If(PushMapping.Area[ObjToString(v["area"])] > 0, PushMapping.Area[ObjToString(v["area"])], 0).(int)).(int)
+			}
+			if v["city"] != nil {
+				myInsert["city"] = If(PushMapping.City[ObjToString(v["city"])] > 0, PushMapping.City[ObjToString(v["city"])], 0).(int)
+			}
+			if v["subtype"] != nil {
+				myInsert["subtype"] = If(PushMapping.Subtype[ObjToString(v["subtype"])] > 0, PushMapping.Subtype[ObjToString(v["subtype"])], 0).(int)
+			}
+			if v["toptype"] != nil {
+				myInsert["toptype"] = If(PushMapping.Toptype[ObjToString(v["toptype"])] > 0, PushMapping.Toptype[ObjToString(v["toptype"])], 0).(int)
+			}
+			if v["buyerclass"] != nil {
+				myInsert["buyerclass"] = If(PushMapping.Buyerclass[ObjToString(v["buyerclass"])] > 0, PushMapping.Buyerclass[ObjToString(v["buyerclass"])], 0).(int)
+			}
+			if v["isValidFile"] != nil {
+				isValidFile, _ := v["isValidFile"].(bool)
+				myInsert["attachment_count"] = If(isValidFile, 1, 0).(int) //附件 :检索库 只有附件字段,无法识别附件数量 暂定为1;为识别有附件
+			}
+			if v["bidamount"] != nil {
+				myInsert["bidamount"] = Int64All(v["bidamount"])
+			}
+			if v["budget"] != nil {
+				myInsert["budget"] = Int64All(v["budget"])
+			}
+			if s_subscopeclass := ObjToString(v["s_subscopeclass"]); s_subscopeclass != "" {
+				subscopeclass := []string{}
+				for _, v := range strings.Split(s_subscopeclass, ",") {
+					if subscopeclass_mapping, ok := PushMapping.Subscopeclass[v]; ok {
+						subscopeclass = append(subscopeclass, fmt.Sprint(subscopeclass_mapping))
+					}
+				}
+				if len(subscopeclass) > 0 {
+					myInsert["subscopeclass"] = strings.Join(subscopeclass, ",")
+				}
+			}
+			//商机管理用户
+			if s.ModuleFlag == "s" {
+				myInsert["userid"] = userId
+				myInsert["entid"] = entId
+				myInsert["deptid"] = deptId
+			}
+			//保存推送表
+			id := PushMysql.Insert(aboutDbMsg[s.ModuleFlag].MysqlTable, myInsert)
+			if id > 0 {
+				redis.Put("pushcache_2_a", redisKey, 1, 86400)
+				resultList = append(resultList, s.InfoFormat(&PushCa{
+					InfoId:     ObjToString(v["_id"]),
+					Date:       now.Unix(),
+					Index:      id,
+					Keys:       matchkeys,
+					FileExists: v["filetext"] != nil,
+				}, &v))
+			}
+		}(v)
+	}
+	wg.Wait()
+	log.Println("数据处理耗时:", time.Since(t2))
+	return
+}
+
+//获取匹配得关键词
+func getKeys(title string, keywords []ViewKeyWord) (str []string) {
+	if len(keywords) > 0 {
+	L:
+		for _, v := range keywords {
+			for _, vk := range v.Keyword {
+				if strings.Contains(title, vk) {
+					str = append(str, v.Keyword...)
+					break L
+				}
+			}
+			for _, va := range v.Appended {
+				if strings.Contains(title, va) {
+					str = append(str, v.Appended...)
+					break L
+				}
+			}
+		}
+	}
+	return
+}

+ 4 - 2
src/jfw/modules/common/src/qfw/util/jy/userMerge.go

@@ -91,7 +91,7 @@ func (this *UserMerge) MergeQuery() (wId, pId, bPhone string, err error) {
 //更新session
 func (this *UserMerge) FlushSession(userData *map[string]interface{}, userId string) {
 	if userData == nil {
-		userData, _ = this.mg.FindById("user", userId, `{"_id":1,"i_shareknow":1,"s_m_openid":1,"s_nickname":1,"s_headimage":1,"s_headimageurl":1,"s_phone":1,"s_m_phone":1,"s_jpushid":1,"s_opushid":1,"s_appponetype":1,"s_appversion":1}`)
+		userData, _ = this.mg.FindById("user", userId, `{"_id":1,"i_shareknow":1,"s_m_openid":1,"s_nickname":1,"s_headimage":1,"s_headimageurl":1,"s_phone":1,"s_m_phone":1,"s_jpushid":1,"s_opushid":1,"s_appponetype":1,"s_appversion":1,"base_user_id":1}`)
 	}
 	sessionVal := make(map[string]interface{})
 	sessionVal["user"] = *userData
@@ -131,6 +131,8 @@ func (this *UserMerge) FlushSession(userData *map[string]interface{}, userId str
 	sessionVal["s_appponetype"], _ = (*userData)["s_appponetype"].(string)
 	sessionVal["s_appversion"], _ = (*userData)["s_appversion"].(string)
 	sessionVal["app_name"] = nickName
-
+	if base_userid := qutil.IntAllDef((*userData)["base_user_id"], 0); base_userid != 0 {
+		sessionVal["base_user_id"] = base_userid
+	}
 	this.sess.SetMultiple(sessionVal)
 }

+ 1 - 0
src/jfw/modules/publicapply/src/ad/entity/struct.go

@@ -18,6 +18,7 @@ type AdInfo struct {
 		StartTime string `json:"startTime"` //开始时间
 		EndTime   string `json:"endTime"`   //结束时间
 	} `json:"o_extend"` //拓展属性
+	S_script string `json:"s_script"` //脚本
 }
 
 //Handle 广告位信息处理

+ 7 - 20
src/jfw/modules/publicapply/src/bidcollection/entity/entity.go

@@ -512,35 +512,22 @@ func GetInfoById(Mgo_bidding mg.MongodbSim, bidding, bidding_back string, idlist
 		return array
 	}
 	m := map[string]bool{}
-	ids := []string{}
+	es_ids := []string{}
 	for _, v := range idlist {
 		if m[qu.ObjToString(v["bid"])] {
 			continue
 		}
 		m[qu.ObjToString(v["bid"])] = true
-		ids = append(ids, qu.ObjToString(v["bid"]))
+		es_ids = append(es_ids, qu.ObjToString(v["bid"]))
 	}
 	infos := map[string]map[string]interface{}{}
-	// log.Println("ids:", len(ids))
-	//redis
-	es_ids := ids
-	for _, v := range ids {
-		info_i := redis.Get("pushcache_1", fmt.Sprintf("info_%s", v))
-		if info_i != nil {
-			info_m, _ := info_i.(map[string]interface{})
-			info_m["_id"] = v
-			infos[v] = info_m
-		} else {
-			es_ids = append(es_ids, v)
-		}
-	}
 	// log.Println("es_ids:", len(es_ids))
 	if len(es_ids) > 0 {
 		list := elastic.Get("bidding", "bidding", fmt.Sprintf(querys, strings.Join(es_ids, `","`), len(es_ids)))
 		if list != nil {
 			for _, v := range *list {
 				_id := qu.ObjToString(v["_id"])
-				v["attachment_count"] = qu.If(v["filetext"] != nil, 1, 0).(int)
+				v["isValidFile"], _ = v["isValidFile"].(bool)
 				infos[_id] = v
 			}
 		}
@@ -549,7 +536,7 @@ func GetInfoById(Mgo_bidding mg.MongodbSim, bidding, bidding_back string, idlist
 	//mongodb bidding
 	//fmt.Println(1)
 	mgo_ids := []primitive.ObjectID{}
-	for _, v := range ids {
+	for _, v := range es_ids {
 		if infos[v] == nil {
 			_id, _ := primitive.ObjectIDFromHex(v)
 			mgo_ids = append(mgo_ids, _id)
@@ -561,7 +548,7 @@ func GetInfoById(Mgo_bidding mg.MongodbSim, bidding, bidding_back string, idlist
 			for _, v := range *list {
 				_id := mg.BsonIdToSId(v["_id"])
 				v["_id"] = _id
-				v["attachment_count"] = qu.If(v["attach_text"] != nil, 1, 0).(int)
+				v["isValidFile"], _ = v["isValidFile"].(bool)
 				infos[_id] = v
 			}
 		}
@@ -580,7 +567,7 @@ func GetInfoById(Mgo_bidding mg.MongodbSim, bidding, bidding_back string, idlist
 			for _, v := range *list {
 				_id := mg.BsonIdToSId(v["_id"])
 				v["_id"] = _id
-				v["attachment_count"] = qu.If(v["attach_text"] != nil, 1, 0).(int)
+				v["isValidFile"], _ = v["isValidFile"].(bool)
 				infos[_id] = v
 			}
 		}
@@ -642,7 +629,7 @@ func InfoFormat(p string, info *map[string]interface{}) *InfoList {
 		Buyer:           qu.ObjToString((*info)["buyer"]),
 		S_winner:        qu.ObjToString((*info)["s_winner"]),
 		Bidopentime:     qu.Int64All((*info)["bidopentime"]),
-		FileExists:      qu.If(config.Config.FileSignBool, qu.IntAll((*info)["attachment_count"]) > 0, false).(bool),
+		FileExists:      qu.If(config.Config.FileSignBool && (*info)["isValidFile"] != nil, (*info)["isValidFile"], false).(bool),
 		Site:            qu.ObjToString((*info)["site"]),
 		Spidercode:      qu.ObjToString((*info)["spidercode"]),
 	}

+ 249 - 0
src/jfw/modules/publicapply/src/subscribePush/entity/historyPush.go

@@ -3,9 +3,15 @@ package entity
 import (
 	"db"
 	"encoding/json"
+	"fmt"
+	"log"
 	"qfw/util"
 	"qfw/util/elastic"
 	"qfw/util/jy"
+	"strconv"
+	"strings"
+	es "subscribePush/entity/service"
+	"time"
 )
 
 type historyPush struct {
@@ -71,3 +77,246 @@ func PushView(userid, allquery, field string, pageNum, pageSize int) (keys []int
 	list = elastic.GetResForJY(INDEX, TYPE, allkeys, allquery, `"title"`, `{"publishtime":"desc"}`, field, (pageNum-1)*pageSize, pageSize)
 	return
 }
+
+const (
+	bidField   = `"_id","title","publishtime","toptype","subtype","type","area","city","s_subscopeclass","buyerclass","budget","bidamount","isValidFile","spidercode","site"`
+	bidTime    = `{"range":{"publishtime":{"gt":%d}}}`
+	bidSort    = `{"publishtime":"desc"}`
+	findfields = `"title"`
+)
+
+type defaultPush struct {
+	UserId     string
+	EntId      int
+	Size       int
+	ModuleFlag string
+}
+
+func DefaultPushList(userId, moduleFlag string, entId int) (keyword []byte, list *[]map[string]interface{}, deptId int) {
+	if userId == "" {
+		return
+	}
+	dp := defaultPush{
+		UserId:     userId,
+		EntId:      entId,
+		Size:       50,
+		ModuleFlag: moduleFlag,
+	}
+	scd, deptid := dp.getUserInfo()
+	if len(scd.Keyword) > 0 {
+		deptId = deptid
+		keyword, _ = json.Marshal(scd.Keyword)
+		//获取查询语句
+		qstr := dp.getDefaultDatasSQL(scd)
+		list = elastic.GetAllByNgram(INDEX, TYPE, qstr, findfields, bidSort, bidField, 0, dp.Size, 0, false)
+	}
+	return
+}
+
+//获取用户信息
+func (d *defaultPush) getUserInfo() (vc *ViewCondition, deptId int) {
+	t1 := time.Now()
+	var isPayBool = false
+	var tmpInfo = struct {
+		Items      []interface{}
+		BuyerClass []interface{}
+		SubType    []interface{}
+		Area       map[string]interface{}
+		SelectType string
+	}{}
+	switch d.ModuleFlag {
+	case "m":
+		//大会员
+		userMap, ok := db.Mgo.FindById("user", d.UserId, `{"o_member_jy":1,"i_member_status":1}`)
+		if !ok || userMap == nil || len(*userMap) == 0 {
+			return &ViewCondition{}, 0
+		}
+		if util.IntAll((*userMap)["i_member_status"]) > 0 {
+			isPayBool = true
+			o_member_jy, _ := (*userMap)["o_member_jy"].(map[string]interface{})
+			tmpInfo.Items, _ = o_member_jy["a_items"].([]interface{})
+			tmpInfo.BuyerClass, _ = o_member_jy["a_buyerclass"].([]interface{})
+			tmpInfo.SubType, _ = o_member_jy["a_infotype"].([]interface{})
+			tmpInfo.Area, _ = o_member_jy["o_area"].(map[string]interface{})
+		}
+	case "v":
+		//超级订阅
+		userMap, ok := db.Mgo.FindById("user", d.UserId, `{"o_vipjy":1,"i_vip_status":1}`)
+		if !ok || userMap == nil || len(*userMap) == 0 {
+			return &ViewCondition{}, 0
+		}
+		if util.IntAll((*userMap)["i_vip_status"]) > 0 {
+			isPayBool = true
+			o_vipjy, _ := (*userMap)["o_vipjy"].(map[string]interface{})
+			tmpInfo.Items, _ = o_vipjy["a_items"].([]interface{})
+			tmpInfo.BuyerClass, _ = o_vipjy["a_buyerclass"].([]interface{})
+			tmpInfo.SubType, _ = o_vipjy["a_infotype"].([]interface{})
+			tmpInfo.Area, _ = o_vipjy["o_area"].(map[string]interface{})
+		}
+	case "s":
+		//商机管理
+		entUserId, _ := strconv.Atoi(d.UserId)
+		if d.UserId == "" || d.EntId == 0 {
+			return &ViewCondition{}, 0
+		}
+		var entInfo map[string]interface{}
+		entInfo, deptId = (&es.MatchJob{}).Start(d.EntId, entUserId)
+		if entInfo != nil && len(entInfo) > 0 {
+			isPayBool = true
+			tmpInfo.Items, _ = entInfo["a_items"].([]interface{})
+			tmpInfo.BuyerClass, _ = entInfo["a_buyerclass"].([]interface{})
+			tmpInfo.SubType, _ = entInfo["a_infotype"].([]interface{})
+			tmpInfo.Area, _ = entInfo["o_area"].(map[string]interface{})
+		}
+	default:
+		//免费用户
+		userMap, ok := db.Mgo.FindById("user", d.UserId, `{"o_jy":1}`)
+		if !ok || userMap == nil || len(*userMap) == 0 {
+			return &ViewCondition{}, 0
+		}
+		o_jy, _ := (*userMap)["o_jy"].(map[string]interface{})
+		if o_jy["a_key"] != nil {
+			tmpInfo.Items, _ = o_jy["a_key"].([]interface{})
+			//信息类型
+			tmpInfo.SubType, _ = o_jy["a_infotype"].([]interface{})
+			//省份
+			tmpInfo.Area, _ = o_jy["o_area"].(map[string]interface{})
+			if util.IntAllDef(o_jy["i_ppstatus"], 0) == 1 && o_jy["o_area_p"] != nil {
+				tmpInfo.Area, _ = o_jy["o_area_p"].(map[string]interface{})
+			}
+		}
+	}
+	vc = &ViewCondition{
+		Buyerclass: util.ObjArrToStringArr(tmpInfo.BuyerClass),
+		Subtype:    util.ObjArrToStringArr(tmpInfo.SubType),
+		Area:       getStringArrFromDbResult(tmpInfo.Area, 1),
+		City:       getStringArrFromDbResult(tmpInfo.Area, 2),
+		SelectType: "1",
+	}
+	//付费用户
+	if isPayBool {
+		d.Size = 1000
+		vc.Keyword = getKeyWordArrFromDbResult(tmpInfo.Items, "", -1)
+	} else {
+		vc.Keyword = getKeyWordArrFromDbResultByFree(tmpInfo.Items, "", -1)
+	}
+	log.Println("获取用户信息耗时:", time.Since(t1).Seconds())
+	return
+}
+
+//获取查询语句
+func (d *defaultPush) getDefaultDatasSQL(scd *ViewCondition) (str string) {
+	query := `{"query":{"bool":{"must":[%s],"should":[%s],"minimum_should_match": %d}}}`
+	query_bool_should := `{"bool":{"should":[%s],"minimum_should_match": 1}}`
+	multi_match := `{"multi_match": {"query": %s,"type": "phrase", "fields": [%s]}}`
+	query_bool_must_and := `{"bool":{"must":[%s]%s}}`
+
+	bools := []string{}
+	musts := []string{}
+	//发布时间最新7天
+	musts = append(musts, fmt.Sprintf(bidTime, time.Now().AddDate(0, 0, -7).Unix()))
+	//省份
+	areaCity := []string{}
+	if len(scd.Area) > 0 {
+		areaquery := `{"terms":{"area":[`
+		for k, v := range scd.Area {
+			if k > 0 {
+				areaquery += `,`
+			}
+			areaquery += `"` + v + `"`
+		}
+		areaquery += `]}}`
+		areaCity = append(areaCity, areaquery)
+	}
+
+	//城市
+	if len(scd.City) > 0 {
+		areaquery := `{"terms":{"city":[`
+		for k, v := range scd.City {
+			if k > 0 {
+				areaquery += `,`
+			}
+			areaquery += `"` + v + `"`
+		}
+		areaquery += `]}}`
+		areaCity = append(areaCity, areaquery)
+	}
+	if len(areaCity) > 0 {
+		musts = append(musts, fmt.Sprintf(query_bool_should, strings.Join(areaCity, ",")))
+	}
+	if len(scd.Subtype) > 0 {
+		subquery := `{"terms":{"subtype":[`
+		for k, v := range scd.Subtype {
+			if k > 0 {
+				subquery += `,`
+			}
+			subquery += `"` + v + `"`
+		}
+		subquery += `]}}`
+		musts = append(musts, subquery)
+	}
+	if len(scd.Buyerclass) > 0 {
+		Buyerclass := `{"terms":{"buyerclass":[`
+		for k, v := range scd.Buyerclass {
+			if k > 0 {
+				Buyerclass += `,`
+			}
+			Buyerclass += `"` + v + `"`
+		}
+		Buyerclass += `]}}`
+		musts = append(musts, Buyerclass)
+	}
+	boolsNum := 0 //should
+	if len(scd.Keyword) > 0 {
+		boolsNum = 1
+		if scd.SelectType == "" || scd.SelectType == "2" {
+			scd.SelectType = "detail\", \"title"
+		} else {
+			scd.SelectType = "title"
+		}
+		multi_match = fmt.Sprintf(multi_match, "%s", "\""+scd.SelectType+"\"")
+
+		for _, v := range scd.Keyword {
+			shoulds := []string{}
+			must_not := []string{}
+			//附加词
+			for _, vv := range v.Keyword {
+				vv = strings.TrimSpace(vv)
+				if vv == "" {
+					continue
+				}
+				shoulds = append(shoulds, fmt.Sprintf(multi_match, "\""+vv+"\""))
+			}
+
+			for _, vv := range v.Appended {
+				vv = strings.TrimSpace(vv)
+				if vv == "" {
+					continue
+				}
+				shoulds = append(shoulds, fmt.Sprintf(multi_match, "\""+vv+"\""))
+			}
+
+			//排除词
+			for _, vv := range v.Exclude {
+				vv = strings.TrimSpace(vv)
+				if vv == "" {
+					continue
+				}
+				must_not = append(must_not, fmt.Sprintf(multi_match, "\""+vv+"\""))
+			}
+
+			//添加
+			if len(shoulds) > 0 {
+				notStr := ""
+				if len(must_not) > 0 {
+					notStr = fmt.Sprintf(`,"must_not":[%s]`, strings.Join(must_not, ","))
+				}
+				bools = append(bools, fmt.Sprintf(query_bool_must_and, strings.Join(shoulds, ","), notStr))
+			}
+		}
+	}
+
+	qstr := fmt.Sprintf(query, strings.Join(musts, ","), strings.Join(bools, ","), boolsNum)
+	log.Println("----", qstr)
+	return qstr
+}

+ 241 - 0
src/jfw/modules/publicapply/src/subscribePush/entity/service/entity.go

@@ -0,0 +1,241 @@
+package service
+
+import (
+	"log"
+	. "mongodb"
+	util "qfw/util"
+	"qfw/util/mysql"
+)
+
+func ClearEnt() {
+	Ents = map[int]*Ent{}
+	EntUsers = map[int]*EntUser{}
+	EntUserDept = map[int]*EntDeptUser{}
+	EntDeptUsers = map[int][]*EntDeptUser{}
+	EntRuleUsers = map[string][]*EntRuleUser{}
+	EntUserRules = map[int][]*EntRuleUser{}
+	EntDepts = map[int]*EntDept{}
+	EntParentDept = map[int][]*EntDeptParent{}
+	EntChildDept = map[int][]*EntDeptParent{}
+	EntDeptDis = map[int][]*EntDistribute{}
+}
+
+//
+func InitEnt(mysql *mysql.Mysql, mgo *MongodbSim, dbName string, entId, entUserId int) {
+	InitEnts(mysql, entId)
+	InitEntUsers(mysql, entUserId)
+	InitEntDeptUsers(mysql, entUserId)
+	InitEntRuleUsers(mysql, entUserId)
+	InitEntDepts(mysql, entId)
+	InitEntDeptParents(mysql, entId)
+	InitEntDistribute(mgo, dbName, entId)
+}
+
+///////////////////////
+var Ents = map[int]*Ent{}
+
+type Ent struct {
+	Id         int
+	Model      int
+	Name       string
+	DeptParent map[int][]int
+	IsNew      int
+}
+
+func InitEnts(Mysql *mysql.Mysql, entId int) {
+	list := Mysql.SelectBySql("select id,model,name from entniche_info where id=? and isNew=1 and status=1 and model in (1,2)", entId)
+	if list == nil {
+		return
+	}
+	for _, v := range *list {
+		id := util.IntAll(v["id"])
+		Ents[id] = &Ent{
+			Id:    id,
+			Model: util.IntAll(v["model"]),
+			Name:  util.ObjToString(v["name"]),
+		}
+	}
+	log.Println("entniche_info加载完成!")
+}
+
+var EntDepts = map[int]*EntDept{}
+
+type EntDept struct {
+	Id     int
+	Pid    int
+	Name   string
+	Nodiff int
+	Subdis int
+}
+
+func InitEntDepts(Mysql *mysql.Mysql, entId int) {
+	list := Mysql.SelectBySql(`select id,name,pid,subdis,nodiff from entniche_department where ent_id=?`, entId)
+	if list == nil {
+		return
+	}
+	for _, v := range *list {
+		id := util.IntAll(v["id"])
+		EntDepts[id] = &EntDept{
+			Id:     id,
+			Pid:    util.IntAll(v["pid"]),
+			Nodiff: util.IntAll(v["nodiff"]),
+			Subdis: util.IntAll(v["subdis"]),
+			Name:   util.ObjToString(v["name"]),
+		}
+	}
+	log.Println("entniche_department加载完成!")
+}
+
+var EntUsers = map[int]*EntUser{}
+
+type EntUser struct {
+	Id    int
+	Name  string
+	Mail  string
+	Phone string
+	Power int
+}
+
+func InitEntUsers(Mysql *mysql.Mysql, entUserId int) {
+	list := Mysql.SelectBySql(`select id,name,mail,phone,power from entniche_user where id=?`, entUserId)
+	if list == nil {
+		return
+	}
+	for _, v := range *list {
+		id := util.IntAll(v["id"])
+		EntUsers[id] = &EntUser{
+			Id:    id,
+			Name:  util.ObjToString(v["name"]),
+			Mail:  util.ObjToString(v["mail"]),
+			Phone: util.ObjToString(v["phone"]),
+			Power: util.IntAll(v["power"]),
+		}
+	}
+	log.Println("entniche_user加载完成!")
+}
+
+//我所有的父部门
+var EntParentDept = map[int][]*EntDeptParent{}
+
+//我所有的子部门
+var EntChildDept = map[int][]*EntDeptParent{}
+
+type EntDeptParent struct {
+	Id  int
+	Pid int
+}
+
+func InitEntDeptParents(Mysql *mysql.Mysql, entId int) {
+	list := Mysql.SelectBySql(`select a.id,a.pid from entniche_department_parent a inner join entniche_department b on (a.id=b.id and b.ent_id=?)`, entId)
+	if list == nil {
+		return
+	}
+	for _, v := range *list {
+		id := util.IntAll(v["id"])
+		pid := util.IntAll(v["pid"])
+		EntParentDept[id] = append(EntParentDept[id], &EntDeptParent{
+			Id:  id,
+			Pid: pid,
+		})
+		EntChildDept[pid] = append(EntChildDept[pid], &EntDeptParent{
+			Id:  id,
+			Pid: pid,
+		})
+	}
+	log.Println("entniche_department_parent加载完成!")
+}
+
+var EntUserDept = map[int]*EntDeptUser{}
+var EntDeptUsers = map[int][]*EntDeptUser{}
+
+type EntDeptUser struct {
+	UserId int
+	DeptId int
+}
+
+func InitEntDeptUsers(Mysql *mysql.Mysql, entUserId int) {
+	list := Mysql.SelectBySql(`select dept_id,user_id from entniche_department_user where user_id=?`, entUserId)
+	if list == nil {
+		return
+	}
+	for _, v := range *list {
+		user_id := util.IntAll(v["user_id"])
+		dept_id := util.IntAll(v["dept_id"])
+		entDeptUser := &EntDeptUser{
+			UserId: user_id,
+			DeptId: dept_id,
+		}
+		EntUserDept[user_id] = entDeptUser
+		EntDeptUsers[dept_id] = append(EntDeptUsers[dept_id], entDeptUser)
+	}
+	log.Println("entniche_department_user加载完成!")
+}
+
+var EntRuleUsers = map[string][]*EntRuleUser{}
+var EntUserRules = map[int][]*EntRuleUser{}
+
+type EntRuleUser struct {
+	UserId int
+	RuleId string
+}
+
+func InitEntRuleUsers(Mysql *mysql.Mysql, entUserId int) {
+	list := Mysql.SelectBySql(`select user_id,rule_id from entniche_user_rule where user_id=?`, entUserId)
+	if list == nil {
+		return
+	}
+	for _, v := range *list {
+		ruleId := util.ObjToString(v["rule_id"])
+		userId := util.IntAll(v["user_id"])
+		entRuleUser := &EntRuleUser{
+			UserId: userId,
+			RuleId: ruleId,
+		}
+		EntRuleUsers[ruleId] = append(EntRuleUsers[ruleId], entRuleUser)
+		EntUserRules[userId] = append(EntUserRules[userId], entRuleUser)
+	}
+	log.Println("entniche_user_rule加载完成!")
+}
+
+var EntDeptDis = map[int][]*EntDistribute{}
+
+type EntDistribute struct {
+	Id         string
+	DeptId     int
+	Area       map[string]interface{}
+	Buyerclass []interface{}
+	Items      []string
+}
+
+func InitEntDistribute(mgo *MongodbSim, dbName string, entId int) {
+	sess := mgo.GetMgoConn()
+	defer mgo.DestoryMongoConn(sess)
+	it := sess.DB(dbName).C("entniche_distribute").Find(map[string]interface{}{
+		"i_status": map[string]interface{}{"$ne": 1},
+		"i_entid":  entId,
+	}).Select(map[string]interface{}{
+		"_id":          1,
+		"i_entid":      1,
+		"i_deptid":     1,
+		"a_items":      1,
+		"o_area":       1,
+		"a_buyerclass": 1,
+	}).Iter()
+	for temp := make(map[string]interface{}); it.Next(&temp); {
+		if temp["i_deptid"] == nil {
+			continue
+		}
+		deptId := util.IntAll(temp["i_deptid"])
+		a_items, _ := temp["a_items"].([]interface{})
+		o_area, _ := temp["o_area"].(map[string]interface{})
+		a_buyerclass, _ := temp["a_buyerclass"].([]interface{})
+		EntDeptDis[deptId] = append(EntDeptDis[deptId], &EntDistribute{
+			Id:         BsonIdToSId(temp["_id"]),
+			DeptId:     deptId,
+			Area:       o_area,
+			Buyerclass: a_buyerclass,
+			Items:      util.ObjArrToStringArr(a_items),
+		})
+		temp = make(map[string]interface{})
+	}
+}

+ 260 - 0
src/jfw/modules/publicapply/src/subscribePush/entity/service/matchjob.go

@@ -0,0 +1,260 @@
+package service
+
+import (
+	"db"
+	"log"
+	util "qfw/util"
+)
+
+//用户基本信息
+type UserInfo struct {
+	Entniche *Entniche
+	SubSet   map[string]interface{}
+}
+
+//
+type Entniche struct {
+	EntId    int    //企业id
+	EntName  string //企业名称
+	DeptId   int    //部门id
+	DeptName string //部门名称
+	DisId    string //分发id
+	UserId   int
+}
+type MatchJob struct {
+}
+
+func (m *MatchJob) Start(entId, entUserId int) (map[string]interface{}, int) {
+	defer util.Catch()
+	defer ClearEnt()
+	InitEnt(db.Mysql, &db.Mgo, "qfw", entId, entUserId)
+	users := m.LoadSubSet(entId)
+	return FinalSub(entUserId, users), EntUserDept[entUserId].DeptId
+}
+
+func (m *MatchJob) LoadSubSet(entId int) map[*UserInfo]bool {
+	defer util.Catch()
+	Users := map[*UserInfo]bool{}
+	sess := db.Mgo.GetMgoConn()
+	defer db.Mgo.DestoryMongoConn(sess)
+	it := sess.DB("qfw").C("entniche_rule").Find(map[string]interface{}{
+		"i_entid": entId,
+	}).Select(map[string]interface{}{
+		"i_entid":    1,
+		"i_deptid":   1,
+		"i_userid":   1,
+		"o_entniche": 1,
+	}).Iter()
+	for _temp := make(map[string]interface{}); it.Next(&_temp); {
+		func(temp map[string]interface{}) {
+			entId := util.IntAll(temp["i_entid"])
+			deptId := util.IntAll(temp["i_deptid"])
+			userId := util.IntAll(temp["i_userid"])
+			if entId == 0 || (deptId == 0 && userId == 0) {
+				return
+			} else if Ents[entId] == nil {
+				log.Println("没有找到该企业", entId)
+				return
+			}
+			entName := Ents[entId].Name
+			if deptId > 0 && EntDepts[deptId] == nil {
+				log.Println("没有找到该部门", entName, entId, deptId)
+				return
+			}
+			deptName := ""
+			if EntDepts[deptId] != nil {
+				deptName = EntDepts[deptId].Name
+			}
+			subSet, _ := temp["o_entniche"].(map[string]interface{})
+			if subSet == nil || len(subSet) == 0 {
+				log.Println("订阅设置为空,过滤掉", entName, entId, deptName, deptId, userId)
+				return
+			}
+			//
+			if deptId > 0 { //部门订阅
+				if Ents[entId].Model != 1 {
+					log.Println("不是统一订阅模式,过滤掉", entName, entId, deptName, deptId)
+					return
+				} else if EntDepts[deptId] == nil {
+					log.Println("没有找到该部门,过滤掉", entName, entId, deptName, deptId)
+					return
+				} else if EntDepts[deptId].Subdis == 0 {
+					log.Println("该部门的订阅分发没有开启,过滤掉", entName, entId, deptName, deptId)
+					return
+				} else if EntDepts[deptId].Nodiff == 0 && EntDeptDis[deptId] == nil {
+					log.Println("该部门开启了订阅分发,没有开启全员无差别接收,但是没有分发规则,过滤掉", entName, entId, deptName, deptId)
+					return
+				}
+				//如果我的上级部门打开了订阅分发,并且开启了全员无差别接收,本部门规则无效
+				for _, dept := range EntParentDept[deptId] {
+					if EntDepts[dept.Pid].Subdis == 1 && EntDepts[dept.Pid].Nodiff == 1 {
+						log.Println("我的上级部门", dept.Pid, "开启了订阅分发和全员无差别,过滤掉", entName, entId, deptName, deptId)
+						return
+					}
+				}
+			} else if userId > 0 { //个人订阅
+				if Ents[entId].Model != 2 {
+					log.Println("不是个人订阅模式,过滤掉", entName, entId, userId)
+					return
+				} else if EntUsers[userId] == nil {
+					log.Println("没有找到该用户,过滤掉", entName, entId, userId)
+					return
+				} else if EntUsers[userId].Power == 0 {
+					log.Println("该用户没有权限,过滤掉", entName, entId, userId)
+					return
+				}
+			}
+			user := &UserInfo{
+				Entniche: &Entniche{
+					EntId:    entId,
+					EntName:  entName,
+					DeptId:   deptId,
+					DeptName: deptName,
+					UserId:   userId,
+				},
+				SubSet: subSet,
+			}
+			log.Println("加载订阅设置", "entId", entId, "entName", entName, "deptId", deptId, "deptName", deptName, "userId", userId)
+			Users[user] = true
+			if deptId <= 0 {
+				return
+			}
+			//分发规则
+			if EntDepts[deptId].Nodiff == 1 {
+				log.Println("该部门开启了全员无差别,分发规则无效", entName, entId, deptName, deptId)
+				return
+			} else if EntDeptDis[deptId] == nil {
+				log.Println("该部门没有分发规则", entName, entId, deptName, deptId)
+				return
+			}
+			itemMap := map[string]interface{}{}
+			items, _ := subSet["a_items"].([]interface{})
+			for _, v := range items {
+				item, _ := v.(map[string]interface{})
+				if item == nil {
+					continue
+				}
+				item_name, _ := item["s_item"].(string)
+				if item_name == "" {
+					continue
+				}
+				itemMap[item_name] = item
+			}
+			for _, dis := range EntDeptDis[deptId] {
+				child_items := []interface{}{}
+				for _, item_name := range dis.Items {
+					if itemMap[item_name] == nil {
+						continue
+					}
+					child_items = append(child_items, itemMap[item_name])
+				}
+				child_subSet := map[string]interface{}{}
+				if len(dis.Buyerclass) > 0 {
+					child_subSet["a_buyerclass"] = dis.Buyerclass
+				}
+				if len(dis.Area) > 0 {
+					child_subSet["o_area"] = dis.Area
+				}
+				if len(child_items) > 0 {
+					child_subSet["a_items"] = child_items
+				}
+				if len(child_subSet) == 0 {
+					continue
+				}
+				child_user := &UserInfo{
+					Entniche: &Entniche{
+						EntId:    user.Entniche.EntId,
+						EntName:  user.Entniche.EntName,
+						DeptId:   user.Entniche.DeptId,
+						DeptName: user.Entniche.DeptName,
+						DisId:    dis.Id,
+					},
+					SubSet: child_subSet,
+				}
+				Users[child_user] = true
+			}
+		}(_temp)
+		_temp = make(map[string]interface{})
+	}
+	return Users
+}
+func FinalSub(entUserId int, users map[*UserInfo]bool) map[string]interface{} {
+	for k, _ := range users {
+		if k.Entniche.DeptId > 0 {
+			k.Entniche.DeptName = EntDepts[k.Entniche.DeptId].Name
+			staffIds := GetDeptUserIds(&UserInfo{
+				Entniche: &Entniche{
+					EntId:    k.Entniche.EntId,
+					EntName:  k.Entniche.EntName,
+					DeptId:   k.Entniche.DeptId,
+					DeptName: k.Entniche.DeptName,
+					DisId:    k.Entniche.DisId,
+				},
+			})
+			if staffIds == nil {
+				continue
+			}
+			if staffIds[entUserId] {
+				return k.SubSet
+			}
+		} else if k.Entniche.UserId > 0 {
+			return k.SubSet
+		} else {
+			continue
+		}
+	}
+	return nil
+}
+func GetDeptUserIds(ui *UserInfo) map[int]bool {
+	if EntDepts[ui.Entniche.DeptId].Subdis == 0 {
+		log.Println(ui.Entniche.EntName, ui.Entniche.EntId, ui.Entniche.DeptName, ui.Entniche.DeptId, "没有开启订阅分发,过滤掉")
+		return nil
+	} else if EntDepts[ui.Entniche.DeptId].Nodiff == 0 && ui.Entniche.DisId == "" {
+		log.Println(ui.Entniche.EntName, ui.Entniche.EntId, ui.Entniche.DeptName, ui.Entniche.DeptId, "没有开启全员无差别接收,并且没有分发规则,过滤掉")
+		return nil
+	}
+	//对我的对着生效的用户
+	myIds := map[int]bool{}
+	//打开了全员无差别,下面所有员工都生效
+	if EntDepts[ui.Entniche.DeptId].Nodiff == 1 {
+		for _, v := range EntDeptUsers[ui.Entniche.DeptId] {
+			myIds[v.UserId] = true
+		}
+		for _, v := range EntChildDept[ui.Entniche.DeptId] {
+			for _, vv := range EntDeptUsers[v.Id] {
+				myIds[vv.UserId] = true
+			}
+		}
+		log.Println(ui.Entniche.EntName, ui.Entniche.EntId, ui.Entniche.DeptName, ui.Entniche.DeptId, "该部门打开了全员无差别", len(myIds), "人接收")
+	} else if ui.Entniche.DisId != "" {
+		for _, v := range EntRuleUsers[ui.Entniche.DisId] {
+			myIds[v.UserId] = true
+		}
+		log.Println(ui.Entniche.EntName, ui.Entniche.EntId, ui.Entniche.DeptName, ui.Entniche.DeptId, "该规则开启了订阅分发", ui.Entniche.DisId, "规则分发了", len(myIds), "人")
+	}
+	//我的上级部门,过滤掉本部门的人
+	for _, v := range EntParentDept[ui.Entniche.DeptId] {
+		//看我的上级部门,有没有开启订阅分发
+		if EntDepts[v.Pid].Subdis == 0 {
+			continue
+		}
+		//看我的上级部门,有没有全员无差别接收
+		if EntDepts[v.Pid].Nodiff == 1 {
+			log.Println(ui.Entniche.EntName, ui.Entniche.EntId, ui.Entniche.DeptName, ui.Entniche.DeptId, ui.Entniche.DisId, "上级部门", v.Pid, "打开了全员无差别开关,过滤掉")
+			return nil
+		}
+		//看我的上级部门,有没有对我设置规则
+		for _, vv := range EntDeptDis[v.Pid] {
+			for _, vvv := range EntRuleUsers[vv.Id] {
+				_, ok := myIds[vvv.UserId]
+				if !ok {
+					continue
+				}
+				delete(myIds, vvv.UserId)
+				log.Println(ui.Entniche.EntName, ui.Entniche.EntId, ui.Entniche.DeptName, ui.Entniche.DeptId, "上级部门", v.Pid, "对我设置的有", vvv.RuleId, "分发规则,此规则作废", vvv.UserId)
+			}
+		}
+	}
+	log.Println(ui.Entniche.EntName, ui.Entniche.EntId, ui.Entniche.DeptName, ui.Entniche.DeptId, ui.Entniche.DisId, "该规则匹配到", len(myIds), "人")
+	return myIds
+}

+ 4 - 1
src/jfw/modules/publicapply/src/subscribePush/entity/vrew.go

@@ -370,11 +370,14 @@ func getstype(stype string) string {
 
 // //关键词 附加词 排除词  省份订阅包
 func getKeyWordArrFromDbResultByFree(a_items []interface{}, item string, index int) (arr []ViewKeyWord) {
-	if a_items == nil {
+	if a_items == nil || len(a_items) == 0 {
 		return
 	}
 	for _, v := range a_items {
 		vmr, _ := v.([]interface{})
+		if len(vmr) == 0 {
+			continue
+		}
 		vm, _ := vmr[0].(map[string]interface{})
 		if item != "" && index >= 0 && item != qutil.ObjToString(vm["s_item"]) {
 			continue

+ 6 - 4
src/jfw/modules/publicapply/src/subscribePush/service/pushList.go

@@ -163,10 +163,12 @@ func (sp *SubscribePush) HasPushHistory() {
 		spqp.PushMysql = db.MysqlPush
 	}
 	hasNextPage, _, list := jy.NewSubscribePush(vipType).Datas(spqp)
-	//免费用户无推送记录生成推送记录
-	if vipType == "" && hasKeyFlag && len(list) == 0 && spqp.IsEmpty() && !isVipFlag && util.Int64All((*user)["i_member_status"]) <= 0 {
-		flag, data := jy.NewSubscribePush().MakeHistoryDatas(db.Mgo, db.MysqlPush, userId, entity.PushView)
-		if flag && data != nil {
+	//免费用户无推送记录生成推送记录=>默认推送调整-付费用户默认1000条 免费不变
+	if spqp.PageNum <= 1 && len(list) == 0 && spqp.IsEmpty() {
+		//flag, data := jy.NewSubscribePush().MakeHistoryDatas(db.Mgo, db.MysqlPush, userId, entity.PushView)
+		flag, data := jy.NewSubscribePush(vipType).MakeHistoryDatasNew(spqp.PushMysql, userId, entId, entity.DefaultPushList)
+		if data != nil {
+			hasNextPage = flag
 			jsonBytes, err := json.Marshal(data)
 			err = json.Unmarshal(jsonBytes, &list)
 			if err != nil {

+ 2 - 1
src/jfw/modules/subscribepay/src/config.json

@@ -109,5 +109,6 @@
 	},
 	"smsServiceRpc":"127.0.0.1:932",
 	"nsq":"192.168.3.240:4260",
-  "nsq_topic": "jy_event"
+  "nsq_topic": "jy_event",
+  "userCenterApi":"https://web-zxl.jydev.jianyu360.com"
 }

+ 1 - 0
src/jfw/modules/subscribepay/src/config/config.go

@@ -73,6 +73,7 @@ type config struct {
 	SmsServiceRpc      string
 	Nsq                string
 	Nsq_Topic          string
+	UserCenterApi      string
 }
 type mgoConf struct {
 	Address           string

+ 49 - 1
src/jfw/modules/subscribepay/src/service/userAccountInfo.go

@@ -14,6 +14,7 @@ import (
 	"qfw/util/elastic"
 	"qfw/util/jy"
 	"qfw/util/redis"
+	"qfw/util/usercenter"
 	"strings"
 	"time"
 	"util"
@@ -354,7 +355,7 @@ func (this *UserAccount) PhoneBind() {
 		}
 		//校验验证码成功【校验是否需要合并】
 		if step == 2 {
-			uData, _ := util.MQFW.FindById("user", userId, `{"s_unionid":1,"s_name":1,"s_nickname":1,"s_headimageurl":1,"l_registedate":1,"i_ispush":1,"i_applystatus":1,"i_sex":1,"s_country":1,"s_province":1,"s_city":1,"s_m_openid":1,"a_m_openid":1}`)
+			uData, _ := util.MQFW.FindById("user", userId, `{"s_unionid":1,"s_name":1,"s_nickname":1,"s_headimageurl":1,"l_registedate":1,"i_ispush":1,"i_applystatus":1,"i_sex":1,"s_country":1,"s_province":1,"s_city":1,"s_m_openid":1,"a_m_openid":1,"base_user_id":1}`)
 			if uData == nil && len(*uData) == 0 {
 				return nil, DBQUERY_ERROR
 			}
@@ -390,6 +391,10 @@ func (this *UserAccount) PhoneBind() {
 				}); bindErr != nil {
 					return nil, bindErr
 				}
+				//用户中台存储  开始
+				ck, _ := this.GetCookie("SESSIONID")
+				usercenter.UpdateBaseUser(util.MQFW, config.Config.UserCenterApi, userId, ck)
+				//用户中台存储  结束
 				jy.CreateUserMerge(util.MQFW, util.Mysql, this.Session()).FlushSession(nil, userId) //刷新session
 			} else if mode == "mergeBind" { //跳转绑定-不合并绑定无效
 				if qutil.Int64All((*uData)["l_registedate"]) > config.AutoMergeTimeStamp { //新微信直接绑定
@@ -410,9 +415,19 @@ func (this *UserAccount) PhoneBind() {
 							"o_jy.i_wxpush":  1,
 						},
 					}) {
+						//用户中台存储  开始
+						ck, _ := this.GetCookie("SESSIONID")
+						usercenter.UpdateBaseUser(util.MQFW, config.Config.UserCenterApi, mongodb.BsonIdToSId(relationPhoneId), ck)
+						//删除user
+						base_userid_del := usercenter.GetBaseUserId(util.MQFW, userId)
+						usercenter.PostUserCenter(config.Config.UserCenterApi+usercenter.UserCenterDelete, usercenter.ContentType_Json, userId, map[string]interface{}{
+							"appid": "10000",
+							"id":    base_userid_del,
+						}, ck)
 						util.MQFW.Del("user", map[string]interface{}{"_id": mongodb.StringTOBsonId(userId)})
 						jy.CreateUserMerge(util.MQFW, util.Mysql, this.Session()).FlushSession(nil, relationPhoneId)
 						redis.Put("session", fmt.Sprintf("usermerge_delete_%s", userId), relationPhoneId, 7*24*60*60)
+						//用户中台存储  结束
 						return rData, nil
 					}
 					return nil, fmt.Errorf("账号自动合并异常")
@@ -548,6 +563,12 @@ func (this *UserAccount) PhoneChange() {
 				log.Printf("%s UserAccount ChangePhone 数据更改手机号异常 \n", userId)
 				return nil, fmt.Errorf("数据更新异常")
 			}
+			//用户中台存储  开始
+			func(phone, userId string) {
+				ck, _ := this.GetCookie("SESSIONID")
+				usercenter.UpdateBaseUser(util.MQFW, config.Config.UserCenterApi, userId, ck)
+			}(phoneVerify, userId)
+			//用户中台存储  结束
 			this.Session().Del(phoneAuthPassSessionKey)
 			jy.CreateUserMerge(util.MQFW, util.Mysql, this.Session()).FlushSession(nil, userId) //刷新session
 		}
@@ -639,6 +660,11 @@ func (this *UserAccount) WxBind() {
 		if bindErr := jy.NewPhoneUtil(util.MQFW).BindWeixin(userId, relationWeixinId, thisPhone, upDateMap); bindErr != nil {
 			return nil, bindErr
 		}
+
+		//关联用户中台base_user_id  双向关系
+		ck, _ := this.GetCookie("SESSIONID")
+		usercenter.UpdateBaseUser(util.MQFW, config.Config.UserCenterApi, userId, ck)
+		usercenter.UpdateBaseUser(util.MQFW, config.Config.UserCenterApi, relationWeixinId, ck)
 		//刷新session
 		jy.CreateUserMerge(util.MQFW, util.Mysql, this.Session()).FlushSession(upDateMap, userId)
 		return map[string]interface{}{
@@ -657,6 +683,7 @@ func (this *UserAccount) WxBind() {
 //    2.解绑的微信存在已绑定的手机号(存在关联关系),解绑后解除关联关系
 func (this *UserAccount) WxUnBind() {
 	userId, _ := this.GetSession("userId").(string)
+	ck, _ := this.GetCookie("SESSIONID")
 	rData, errMsg := func() (interface{}, error) {
 		//认证校验
 		//if pass, data := authenticationCheck(this.GetSession(phoneAuthPassSessionKey)); !pass {
@@ -690,6 +717,25 @@ func (this *UserAccount) WxUnBind() {
 			//公众号微信关注移至另一用户中  此时微信公众号用户session问题错乱
 			if saveId := util.MQFW.Save("user", unsetMap); saveId == "" {
 				return nil, DBUPDATE_ERROR
+			} else {
+				//用户中台存储  开始
+				func(phone, userid string) {
+					formdata := map[string]interface{}{
+						"appid":    "10000",
+						"unionid":  qutil.ObjToString((*unsetMap)["s_unionid"]),
+						"s_openid": s_m_openid,
+					}
+					if qutil.ObjToString((*unsetMap)["s_nickname"]) != "" {
+						formdata["nickname"] = qutil.ObjToString((*unsetMap)["s_nickname"])
+					}
+					if qutil.ObjToString((*unsetMap)["s_headimageurl"]) != "" {
+						formdata["headimg"] = qutil.ObjToString((*unsetMap)["s_headimageurl"])
+					}
+					if qutil.ObjToString((*unsetMap)["a_m_openid"]) != "" {
+						formdata["a_openid"] = qutil.ObjToString((*unsetMap)["a_m_openid"])
+					}
+					usercenter.AddBaseUser(util.MQFW, config.Config.UserCenterApi, userid, formdata, ck)
+				}(phone, saveId)
 			}
 			flushWxsession = true
 		}
@@ -703,6 +749,8 @@ func (this *UserAccount) WxUnBind() {
 		if err := jy.NewPhoneUtil(util.MQFW).UnBindWeixin(userId, wId); err != nil {
 			return nil, err
 		}
+		//解除baseuser绑定
+		usercenter.UpdateBaseUser(util.MQFW, config.Config.WebDomain, userId, ck)
 
 		//微信解绑成功
 		//1.微信账户刷新session

BIN
src/jfw/modules/subscribepay/src/subscribepay


+ 6 - 5
src/jfw/modules/weixin/src/config.json

@@ -16,11 +16,11 @@
     "weixinrpcport": "8083",
     "webrpcport": "127.0.0.1:8084",
     "jyop_webrpcport": "127.0.0.1:8012",
-    "webdomain": "https://web-ws.jydev.jianyu360.com",
-    "appid":"wx5b1c6e7cc4dac0e4",
-    "appsecret":"b026103ffebd2291b3edb7a269612112",
+    "webdomain": "https://web-zxl.jydev.jianyu360.com",
+    "appid":"wxdedd73f450993685",
+    "appsecret":"d55898fde0b7887e5fe4660bd2494700",
     "apptoken": "top2022top2022",
-    "proxysess": "https://web-ws.jydev.jianyu360.com/front/sess/%s",
+    "proxysess": "https://web-zxl.jydev.jianyu360.com/front/sess/%s",
     "followCompany": 10,
     "welcomemsg": "用剑鱼标讯,所有功能完全免费,\n和传统的会员制说再见!\n\n<a href='%s'>点击这里</a>设置关键词,或直接回复“订阅 关键词”,如“订阅 教学设备”,您将随时随地接收招标信息!\n\n剑鱼标讯,让投标无限可能!",
     "tpl_subscribe_push_id": "IY_RWWzMlwDK6hcd6RAzTec6qre8n5r8PNOOUM_hgk0",
@@ -127,5 +127,6 @@
     "pcQrCode":{
     		"10":true,"11":true,"12":true,"13":true,"14":true,"17":true,"18":true,"19":true
     },
-    "namePrefix":"JY_%s"
+    "namePrefix":"JY_%s",
+    "userCenterApi":"https://web-zxl.jydev.jianyu360.com"
 }

+ 13 - 0
src/jfw/modules/weixin/src/wx/wx.go

@@ -19,6 +19,7 @@ import (
 	"tools"
 
 	"qfw/util/jy"
+	"qfw/util/usercenter"
 
 	"github.com/SKatiyar/qr"
 	_ "github.com/influxdata/influxdb-client"
@@ -340,6 +341,18 @@ func saveUser(u *UserInfo, source, pre, RSource, CSource string) (bool, string,
 			}
 		}
 		_id := tools.MQFW.Save("user", newUser)
+		if _id != "" {
+			//用户中台存储  开始
+			formdata := map[string]interface{}{
+				"appid":    "10000",
+				"headimg":  u.HeadImageUrl,
+				"nickname": util.If(u.Nickname != "", u.Nickname, newUser["s_jyname"]),
+				"s_openid": u.OpenId,
+				"unionid":  u.UnionId,
+			}
+			usercenter.AddBaseUser(tools.MQFW, util.ObjToString(config.Sysconfig["userCenterApi"]), _id, formdata, &http.Cookie{})
+
+		}
 		//逻辑转到用户完成绑定手机号时写入nsq队列
 		// if fromid != "" && fromid != _id {
 		// 	//被邀请新用户

+ 1 - 1
src/jfw/public/dataexport.go

@@ -143,7 +143,7 @@ func (this *BidSearchExport) PassBidSearchExport() (returnData map[string]interf
 		_, _, keywords := jy.InterceptSearchKW(this.Keywords, isIntercept, len(this.Industry) == 0)
 		keywords = strings.Replace(keywords, "+", " ", -1)
 		excludes := []string{}
-		if len(strings.Split(this.Notkey, " ")) > 0 {
+		if this.Notkey != "" && len(strings.Split(this.Notkey, " ")) > 0 {
 			excludes = strings.Split(this.Notkey, " ")
 		}
 		KeyWordSave = append(KeyWordSave, dataexport.KeyWord{Keyword: keywords, Exclude: excludes})

BIN
src/web/staticres/common-module/active/2022.7/button-middle@2x.png


BIN
src/web/staticres/common-module/active/2022.7/button-small@2x.png


BIN
src/web/staticres/common-module/active/2022.7/content-yure@2x.png


BIN
src/web/staticres/common-module/active/2022.7/coupon-bg@2x.png


BIN
src/web/staticres/common-module/active/2022.7/dialog-bg-big@2x.png


BIN
src/web/staticres/common-module/active/2022.7/dialog-bg@2x.png


BIN
src/web/staticres/common-module/active/2022.7/entniche-shangji@2x.png


BIN
src/web/staticres/common-module/active/2022.7/entniche-zhuanjia@2x.png


BIN
src/web/staticres/common-module/active/2022.7/float-button-bg@2x.png


BIN
src/web/staticres/common-module/active/2022.7/gift-box.png


BIN
src/web/staticres/common-module/active/2022.7/header-banner.png


BIN
src/web/staticres/common-module/active/2022.7/icon-coupon@2x.png


BIN
src/web/staticres/common-module/active/2022.7/more-fuli-text@2x.png


+ 622 - 0
src/web/staticres/common-module/active/2022.7/task-202207.css

@@ -0,0 +1,622 @@
+.content-container img,
+.header-banner img,
+.point-img img {
+  display: block;
+  width: 100%;
+}
+.section:not(:first-of-type, :last-of-type) {
+  margin-bottom: .8rem;
+}
+.header-banner {
+  position: relative;
+}
+.header-strategy {
+  position: relative;
+  margin-top: -0.04rem;
+  background-color: #D10F06;
+  z-index: 1;
+}
+
+.content-container {
+  padding: .48rem 0;
+  background: linear-gradient(127deg, #FF6A63 0%, #D54841 100%);
+}
+.section {
+  padding: 0 .24rem;
+  margin-bottom: .48rem;
+}
+.section .section-header {
+  margin-bottom: .24rem;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+.section .section-content {
+  position: relative;
+}
+.section .section-footer {
+  margin-top: .3rem;
+}
+
+.section .section-header-button {
+  width: 13.92rem;
+}
+
+.section-button {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  font-size: .4rem;
+  font-weight: bold;
+  color: #E8100D;
+  line-height: .46rem;
+  background-color: transparent;
+  background-repeat: no-repeat;
+  background-size: contain;
+  cursor: pointer;
+}
+.section-button:disabled {
+  color: #FF7876;
+}
+
+.section-button.button-middle {
+  width: 4.8rem;
+  height: 1.04rem;
+  background-image: url(/common-module/active/2022.7/button-middle@2x.png);
+  background-size: 100% 100%;
+}
+.section-button.button-small {
+  width: 3.36rem;
+  height: 0.96rem;
+  background-image: url(/common-module/active/2022.7/button-small@2x.png);
+  background-size: 100% 100%;
+}
+
+
+.section-yure .content-info {
+  position: absolute;
+  left: 50%;
+  bottom: .3rem;
+  transform: translateX(-50%);
+  color: #fff;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+}
+.section-yure .c-info-text {
+  display: flex;
+  align-items: center;
+  font-size: .44rem;
+  font-family: 'YouSheBiaoTiHei';
+  line-height: .52rem;
+  text-shadow: 2px 3px 0px #CF1627;
+  white-space: nowrap;
+}
+.section-yure .c-info-text .num {
+  font-size: .82rem;
+  line-height: 1rem;
+}
+
+.section-more-activities .section-header {
+  padding: 0 .18rem;
+}
+
+.section-fuli1 .coupon-list {
+  display: flex;
+  flex-wrap: wrap;
+}
+.section-fuli1 .coupon-item {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  width: 3.34rem;
+  height: 3.44rem;
+  margin: .14rem 0;
+  margin-right: .28rem;
+  font-size: .32rem;
+  color: #E80E0D;
+  background-image: url(/common-module/active/2022.7/coupon-bg@2x.png);
+  background-repeat: no-repeat;
+  background-size: contain;
+  text-align: center;
+}
+.section-fuli1 .coupon-item:nth-of-type(2n) {
+  margin-right: 0;
+}
+.coupon-item .coupon-title {
+  line-height: .68rem;
+}
+.coupon-item .coupon-value .num {
+  font-size: 1.12rem;
+  line-height: 1.02rem;
+}
+.coupon-item .section-button {
+  margin-top: .32rem;
+}
+.coupon-item .button-small {
+  width: 2.36rem;
+  height: 0.76rem;
+}
+.coupon-item .coupon-text {
+  margin: .12rem;
+  font-size: .24rem;
+  color: #fff;
+  white-space: nowrap;
+}
+.section-fuli1 .section-footer {
+  margin: .8rem 0;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+.m-list-item-text {
+  color: #fff;
+}
+
+.section-fuli2 .mission-list {
+  /* background-color: pink; */
+}
+.section-fuli2 .section-header {
+  margin-bottom: 0;
+}
+.section-fuli2 .mission-list-img {
+  width: 100%;
+  position: absolute;
+  top: 50%;
+  left: 50%;
+  transform: translate(-50%,-50%) scale(1.2);
+  z-index: 1;
+}
+
+.section-fuli3 .section-header {
+  margin-bottom: .24rem;
+}
+.section-fuli3 .entniche-card-list {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+}
+.section-fuli3 .entniche-card-item {
+  width: 3.36rem;
+  height: 5.61rem;
+  background-repeat: no-repeat;
+  background-size: contain;
+}
+.entniche-card-item.shangji {
+  background-image: url(/common-module/active/2022.7/entniche-shangji@2x.png);
+}
+.entniche-card-item.zhuanjia {
+  background-image: url(/common-module/active/2022.7/entniche-zhuanjia@2x.png);
+}
+.section-fuli3 .button-group {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+.section-fuli3 .button-group .section-button {
+  flex: 1;
+  font-size: .32rem;
+  font-weight: bold;
+  height: 0.72rem;
+  line-height: .28rem;
+  border-radius: .5rem;
+}
+.section-fuli3 .learn-more {
+  margin-right: .3rem;
+  font-weight: normal;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  border: 1px solid #fff;
+  color: #fff;
+}
+
+.section-fuli3 .text {
+  margin: .64rem 0;
+  font-size: .28rem;
+  line-height: .48rem;
+  color: #fff;
+  text-align: center;
+}
+
+.fixed-top {
+  position: fixed;
+  top: 0.32rem;
+  left: 0;
+  width: 100%;
+  z-index: 2;
+}
+.fixed-right {
+  position: fixed;
+  top: 3rem;
+  right: .16rem;
+  display: flex;
+  flex-direction: column;
+  z-index: 2;
+}
+.fixed-action-button {
+  margin-bottom: .18rem;
+  padding-right: 0.14rem;
+  color: #fff;
+  width: 0.86rem;
+  height: 0.92rem;
+  font-size: .24rem;
+  line-height: .28rem;
+  background-color: transparent;
+  background-image: url(/common-module/active/2022.7/float-button-bg@2x.png);
+  background-repeat: no-repeat;
+  background-size: contain;
+}
+
+.timeline-list {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  height: 100%;
+  margin: 0 .16rem;
+  border-radius: .16rem;
+  overflow: hidden;
+}
+.timeline-item {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  flex: 1;
+  height: 100%;
+  padding: .08rem 0;
+  font-size: .24rem;
+  color: #171826;
+  background-color: #fff;
+  cursor: pointer;
+}
+.timeline-item:not(:last-of-type) {
+  border-right: 1px solid #ececec;
+}
+.timeline-item .t-left {
+  font-size: .28rem;
+  font-weight: bold;
+  line-height: .32rem;
+}
+.timeline-item .t-r-top {
+  line-height: .32rem;
+}
+.timeline-item .t-r-bottom {
+  display: flex;
+  align-items: center;
+  flex-direction: column;
+}
+.timeline-item .t-r-b-l,
+.timeline-item .t-r-b-l2 {
+  margin: .08rem 0;
+}
+
+/* 第一种类型 */
+.timeline-item .t-r-b-l {
+  color: #5E5B5B;
+}
+.timeline-item .t-r-b-r {
+  color: #E30101;
+}
+/* 第二种 */
+.timeline-item .t-r-bottom {
+  color: #E30101;
+}
+
+.timeline-item.active {
+  color: #fff;
+  background-color: #E30101;
+}
+/* 高亮1 */
+.timeline-item.active .t-r-b-l,
+.timeline-item.active .t-r-b-l2,
+.timeline-item.active .t-r-b-r,
+.timeline-item.active .t-r-b-r2 {
+  color: #fff;
+}
+
+
+/* 我的奖励 */
+.reward-card-container {
+  max-height: 60vh;
+  min-height: 50vh;
+}
+.reward-section .van-popup__close-icon {
+  background: #FF8411;
+  border-radius: 50%;
+  padding: .08rem;
+  color: #fff;
+  font-size: .24rem;
+}
+.reward-section .van-popup__close-icon--top-right {
+  top: .48rem;
+  right: .32rem;
+}
+.reward-section .r-header {
+  padding: .44rem .32rem .28rem;
+  height: 1.28rem;
+  font-size: .4rem;
+  line-height: .46rem;
+  background: linear-gradient(to bottom, #FFE5B3 0%, #FFEFDD 100%);
+}
+.reward-section .el-dialog {
+  border-radius: 25px;
+  background: #FFEFDD;
+}
+.reward-section .el-dialog__header {
+  padding: 28px 24px 12px;
+  text-align: center;
+}
+.reward-section .el-dialog__title {
+  color: #F01313;
+  font-size: 24px;
+  font-weight: bold;
+  line-height: 28px;
+}
+.reward-section .el-dialog__close {
+  font-size: 26px;
+  font-weight: bold;
+  color: #F01313!important;
+}
+.reward-section .el-dialog__body {
+  padding-left: 24px;
+  padding-right: 24px;
+}
+.reward-card {
+  padding: 8px;
+  background: #FDF0E1;
+}
+.reward-list-header {
+  font-size: 20px;
+  font-weight: bold;
+  color: #1D1D1D;
+  line-height: 22px;
+}
+.reward-list {
+  padding: 6px 0;
+}
+.reward-card .j-icon {
+  width: 48px;
+  height: 48px;
+}
+.reward-card .tr {
+  display: flex;
+}
+.reward-card .td {
+  display: flex;
+  align-items: center;
+  padding: 16px;
+}
+.reward-card .tr .td:nth-of-type(1),
+.reward-card .tr .td:nth-of-type(2) {
+  flex: 4;
+}
+.reward-card .tr .td:nth-of-type(3) {
+  flex: 3;
+}
+.reward-card .tr .td:nth-of-type(4) {
+  flex: 1;
+}
+.reward-card .r-l-i-name .j-icon {
+  margin-right: 4px;
+}
+.table-line {
+  height: 5px;
+  width: 100%;
+  background: #F7A661;
+  box-shadow: inset 0px 6px 8px 1px rgba(255, 255, 255, 0.4);
+  border-radius: 20px;
+}
+.reward-action-button {
+  padding: 2px 12px;
+  color: #fff;
+  font-size: 16px;
+  line-height: 24px;
+  background: linear-gradient(176deg, #FA8920 0%, #FB4D27 65%, #DD1515 100%);
+  border-radius: 14px;
+}
+.reward-empty {
+  font-size: 16px;
+  font-weight: 400;
+  color: #AAAAAA;
+  line-height: 24px;
+  text-align: center;
+  padding-top: 78px;
+  padding-bottom: 67px;
+}
+
+.reward-list-item {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  padding: .36rem 0;
+}
+.reward-list-item:not(:last-of-type) {
+  border-bottom: 1px solid rgba(0, 0, 0, 0.05);
+}
+.reward-list-item .r-l-i-l {
+  width: .8rem;
+  height: .8rem;
+}
+.reward-list-item .r-l-i-c {
+  margin: 0 .16rem;
+  flex: 1;
+}
+.reward-list-item .r-l-i-c-t {
+  margin-bottom: .16rem;
+  display: flex;
+  align-items: center;
+}
+.reward-list-item .r-l-i-action {
+  font-size: .48rem;
+  color: #FFCD6A;
+}
+.reward-list-item .reward-text {
+  margin-right: .16rem;
+  font-size: .32rem;
+  color: #171826;
+  line-height: .4rem;
+}
+.reward-list-item .receive-from {
+  padding: .04rem .16rem;
+  font-size: .2rem;
+  color: #171826;
+  line-height: .32rem;
+  background: linear-gradient(135deg, #FFCC66 0%, #FFECC5 100%);
+  border-radius: .2rem;
+  white-space: nowrap;
+}
+.reward-list-item  .receive-time {
+  font-size: .24rem;
+  color: #9B9CA3;
+  line-height: .28rem;
+}
+
+
+.activity-rules-button {
+  position: absolute;
+  right: 0;
+  top: 30%;
+  z-index: 9;
+  padding: .12rem .08rem;
+  writing-mode: vertical-lr;
+  background: linear-gradient(272deg, rgba(233, 138, 95, 0.5) 0%, #DB5634 100%);
+  border-radius: .12rem 0px 0px .12rem;
+  color: #fff;
+  font-size: .24rem;
+  line-height: .28rem;
+  /* border: 1px solid #FCAB11; */
+}
+.activity-rules-button::after {
+  /* content: ''; */
+  position: absolute;
+  top: -0.04rem;
+  bottom: -0.04rem;
+  left: -0.04rem;
+  right: -0.04rem;
+  background: linear-gradient(180deg, rgba(255, 216, 216, 0), rgba(255, 216, 216, 1));
+  z-index: -1;
+  border-radius: .12rem 0px 0px .12rem;
+}
+
+#active-tip-modal.van-popup {
+  background:transparent;
+}
+#active-tip-modal[data-modal-type='success'] .modal-dialog.active-tip--success,#active-tip-modal[data-modal-type='over'] .modal-dialog.active-tip--over,#active-tip-modal[data-modal-type='code'] .modal-dialog.active-tip--rule {
+  display:flex;
+}
+.active-tip--success,.active-tip--over,.active-tip--rule {
+  position:relative;
+  display:flex;
+  flex-direction:column;
+  align-items:center;
+  width:6.06rem;
+  height:8rem;
+  margin:0 auto;
+  top:calc(50% - 4rem);
+  border-radius:0.24rem;
+  overflow:hidden;
+}
+.active-tip--rule {
+  height: 11.6rem;
+}
+.active-tip--success button,.active-tip--over button,.active-tip--rule button {
+  width:4.62rem;
+  height:0.96rem;
+  font-size:0.32rem;
+  font-weight:500;
+  color:#fff;
+  border-radius:0.48rem;
+  background: linear-gradient(90deg, #FE542F 0%, #F01313 100%);
+  box-shadow: inset 0px 0px 4px 1px rgba(236,143,4,0.25);
+}
+.active-tip--success .bg-image,.active-tip--rule .bg-image {
+  position:absolute;
+  z-index:-1;
+  width:100%;
+}
+.active-tip--success p span {
+  display:inline-block;
+  margin-top:0.22rem;
+  margin-bottom:1rem;
+  font-size:0.24rem;
+  line-height:0.28rem;
+}
+.active-tip--success p {
+  font-size:0.32rem;
+  font-weight:400;
+  color:#171826;
+  line-height:0.38rem;
+  text-align:center;
+}
+.active-tip--success h5,.active-tip--rule h5 {
+  font-size:0.4rem;
+  font-weight:bold;
+  line-height:0.46rem;
+}
+.active-tip--success h5 {
+  margin-top:3rem;
+  margin-bottom:1rem;
+}
+.active-tip--rule h5 {
+  margin-top:2.5rem;
+  margin-bottom:.32rem;
+}
+.active-tip--over {
+  background-color:#fff;
+}
+.active-tip--over h4 {
+  font-size:0.4rem;
+  font-weight:bold;
+  color:#171826;
+  line-height:0.56rem;
+  margin-top:0.64rem;
+  margin-bottom:0.4rem;
+}
+.active-tip--over p {
+  margin-top:0.32rem;
+  margin-bottom:0.56rem;
+  font-size:0.28rem;
+  font-weight:500;
+  color:#5F5E64;
+  line-height:0.4rem;
+  text-align:center;
+}
+.active-tip--rule .rule-content .rule-item  + .rule-item {
+  margin-top: 0.16rem;
+}
+.active-tip--rule .rule-content .rule-item {
+  display: flex;
+  flex-direction: row;
+}
+.active-tip--rule .rule-content .rule-index {
+  padding-right: 0.04rem;
+}
+.active-tip--rule.max {
+  height: 8rem;
+}
+.active-tip--rule.max .rule-content {
+  max-height: 3.68rem;
+  overflow: auto;
+}
+.active-tip--rule .rule-content {
+  font-size:0.22rem;
+  font-weight:400;
+  color:#171826;
+  line-height: 0.28rem;
+  padding: 0 0.24rem;
+  margin-bottom: 0.3rem;
+  max-height: 5.4rem;
+  overflow-y: scroll;
+}
+
+.close-dialog-icon img {
+  width:0.32rem;
+}
+.close-dialog-icon {
+  position:absolute;
+  top:0;
+  right:0;
+  padding:0.24rem;
+  cursor:pointer;
+}

+ 1031 - 0
src/web/staticres/common-module/active/2022.7/task-202207.js

@@ -0,0 +1,1031 @@
+function Point (x, y) {
+  this.x = x
+  this.y = y
+}
+function Map (w, h) {
+  this.width = w
+  this.height = h
+}
+// 画布中生成随机不重叠的坐标
+// 坐标点以左上角为中心
+function RandomCoordinate (conf) {
+  conf = conf || {}
+  this.el = conf.el || '' // 画布选择器或者dom
+  this.pointSize = conf.pointSize || new Map(1, 1) // 坐标点半径(最大)
+  this.total = conf.total || 1 // 生成多少个随机不重叠坐标
+  this.pointCoordList = [] // 生成坐标点数组
+
+  this.init = function () {
+    if (!this.el) return console.warn('画布选择器必传')
+    // 获取画布宽高
+    this.map = this.getMapSize()
+    this.getPointCoordLimits()
+    this.create()
+  }
+
+  this.getMapSize = function () {
+    this.$el = $(this.el)
+    var w = this.$el.width()
+    var h = this.$el.height()
+    return new Map(w, h)
+  }
+
+  this.getPointCoordLimits = function () {
+    var xMax = this.map.width - this.pointSize.width
+    var yMax = this.map.height - this.pointSize.height
+    if (xMax <= 0) {
+      xMax = 1
+    }
+    if (yMax <= 0) {
+      yMax = 1
+    }
+    this.coordLimits = new Point(xMax, yMax)
+  }
+
+  // this.check
+  // 检查是否和已创建的有重叠
+  this.checkListOverlap = function (p) {
+    if (this.pointCoordList.length <= 0) return true
+    var pass = true // pass,所有都不重叠
+    for (var i = 0; i < this.pointCoordList.length; i++) {
+      var overlap = this.checkOverlap(p, this.pointCoordList[i])
+      if (overlap) {
+        pass = false
+        break
+      }
+    }
+    return pass
+  },
+  // point为矩形左上的碰撞检测:碰撞返回true
+  // 利用两圆相切,圆心距离小于2r表示两圆相交(r圆半径)。把矩形对角线看作圆的直径
+  // 如果两个矩形左上角的点间距离大于矩形对角线长度,则认为两矩形无碰撞(无重叠)
+  // 参考:https://segmentfault.com/a/1190000017463616
+  this.checkOverlap = function (nPoint, oPoint) {
+    // 两矩形左上角坐标距离(三角函数)
+    // https://www.qttc.net/171-javascript-get-two-points-distance.html
+    var dx = Math.abs(nPoint.x - oPoint.x)
+    var dy = Math.abs(nPoint.y - oPoint.y)
+    var distance = Math.sqrt(dx * dx + dy * dy)
+
+    // 矩形对角线长度
+    var w = this.pointSize.width
+    var h = this.pointSize.height
+    var diagonal = Math.sqrt(w * w + h * h)
+
+    return distance <= diagonal
+  }
+
+  // 创建一个坐标
+  this.createOne = function () {
+    var createTimes = 0
+    var createFailTimes = 0
+    var maxCreateFailTime = 200
+    var x,y
+    while (createFailTimes < maxCreateFailTime) {
+      createTimes++
+      x = Math.floor(Math.random() * this.coordLimits.x)
+      y = Math.floor(Math.random() * this.coordLimits.y)
+      var point = new Point(x, y)
+      var pass = this.checkListOverlap(point)
+      if (pass) {
+        this.pointCoordList.push(point)
+        break
+      } else {
+        createFailTimes++
+      }
+    }
+    if (createFailTimes >= maxCreateFailTime) {
+      console.log('随机生成坐标%s次失败,停止随机生成', maxCreateFailTime)
+    } else {
+      console.log('随机生成坐标次数:%s,\n随机生成坐标失败次数:%s\n获得坐标:', createTimes, createFailTimes, JSON.stringify(point))
+    }
+  }
+
+  this.create = function () {
+    for (var i = 0; i < this.total; i++) {
+      this.createOne()
+    }
+    this.pointCoordList = this.pointCoordList.sort(function (a, b) {
+      return a.x - b.x
+    })
+  }
+
+  this.init()
+}
+
+// 判断活动是否结束
+var initPageTime = new Date().getTime()
+var initActiveOverCheck = -1
+function activeOverCheck (endTime, callback) {
+  if (initPageTime >= endTime) {
+    return callback()
+  }
+  clearTimeout(initActiveOverCheck)
+  var reloadTime = endTime - new Date().getTime()
+  if (reloadTime <= (10 * 60 * 1000) ) {
+    initActiveOverCheck = setTimeout(function () {
+      callback && callback()
+    }, reloadTime)
+  }
+}
+
+// 未定义兼容
+try {
+  var shareSheet = appShareSheet
+} catch (error) {
+  var shareSheet = {}
+  console.log(error)
+}
+var task = new Vue({
+  el: '#main-app',
+  delimiters: ['${', '}'],
+  components: {
+    appShareSheet: shareSheet
+  },
+  data: {
+    platform: 'app',
+    conf: {
+      before: 0, // 单位: s
+      clock: '10:00:00',
+      end: 0, // 单位: s
+      now: 0, // 单位: s
+      start: 0 // 单位: s
+    },
+    activeState: '',
+    lastTimestamp: 0, // 单位: ms
+    timeDuration: {
+      yure: '', // 预热活动时间7.25-7.31
+      active: '' // 活动时间8.1-8.14
+    },
+    yureConf: {
+      total: 0,
+      got: false
+    },
+    yureInfo: {
+      timerId: null,
+      tipText: '',
+      buttonText: '点击免费领',
+      buttonDisabled: false
+    },
+    couponList: [],
+    progress: {
+      min: 0,
+      max: 1500,
+      current: 0, // 当前剑鱼币
+      pointImgMap: {
+        unreceived: '/common-module/active/2022.5.20/unreceived@2x.png',
+        received: '/common-module/active/2022.5.20/received@2x.png',
+        wait: '/common-module/active/2022.5.20/received@2x.png'
+      },
+      anchorList: [
+        {
+          id: '',
+          className: 'first',
+          rate: 0, // 进度,单位%,最大为100
+          pointImg: '', // ''/unreceived/received
+          anchorText: '0剑鱼币'
+        },
+        {
+          id: '800',
+          className: 'unreceived',
+          rate: 80,
+          pointImg: 'unreceived',
+          anchorText: '800剑鱼币',
+          tipText: '1个月超级订阅'
+        },
+        {
+          id: '1500',
+          className: 'unreceived',
+          rate: 100,
+          pointImg: 'unreceived',
+          anchorText: '1500剑鱼币',
+          tipText: '1个月超级订阅'
+        }
+      ],
+    },
+    // 任务球
+    missionsList: [
+      {
+        id: 'buyvip',
+        className: '',
+        x: 0.2,
+        y: 0.94, // rem
+        num: 800,
+        unit: '剑鱼币',
+        complete: false,
+        hide: true,
+        name: '购买超级订阅' // 任务描述
+      },
+      {
+        id: 'invite',
+        className: 'delay-100',
+        x: 2.84,
+        y: 0.06,
+        num: 500,
+        unit: '剑鱼币',
+        complete: false,
+        hide: true,
+        name: '邀请领好礼'
+      },
+      {
+        id: 'share',
+        className: 'delay-300',
+        x: 4.8,
+        y: 0.82,
+        num: 200,
+        unit: '剑鱼币',
+        complete: false,
+        hide: true,
+        name: '分享活动'
+      }
+    ],
+    copyLinkText: location.href,
+    rewardList: [],
+    dialog: {
+      show: false,
+      giftMonth: 1,
+      type: 'rule',
+      myReward: false // 奖励弹窗
+    },
+    rulesList: [
+      {
+        text: '活动时间:预热期:7.25-7.31 、活动期:8.1-8.14。'
+      },
+      {
+        text: '预热福利:预热期内用户每天10点开始领取,每天限量500份,每天0点数量更新,每人仅限领取一次,数量有限,先到先得。'
+      },
+      {
+        text: '福利一:官方补贴限时抢 购买超级订阅立减:活动期间内新购、续费、升级用户均可参加,通过活动页领取优惠券后购买超级订阅可享受满减,不同额度优惠券一人仅限领取1张,优惠券仅限领取后活动期内使用,过期无效。'
+      },
+      {
+        text: '福利二:做任务 得2个月超级订阅:活动期内,用户分别完成各任务即可获得相对应的剑鱼币,达到1000剑鱼币领1个月超级订阅,达到1500剑鱼币领1个月超级订阅,领取后在原有购买时间上延长所领取奖励的时长,在订单支付期间,完成【购买超级订阅】可获得800剑鱼币,用户新购、续费、升级皆可获得剑鱼币奖励,完成【邀请领好礼】可获得500剑鱼币,完成【分享活动】可获得200剑鱼币;完成购买超级订阅、邀请领好礼、分享活动三个任务且活动页剑鱼币累计达到1000剑鱼币或1500剑鱼币即可领取超级订阅,累计可领2个月,通过其他形式获取的剑鱼币将不作为领取奖励的依据,领取后在【我的奖励】中查看。'
+      },
+      {
+        text: '福利三:大会员最高立减7999元 送6个月使用时长:活动期内商机版2.0最高立减3199元,购买赠送6个月使用时长,专家版2.0最高立减7999元,购买赠送6个月使用时长,点击【了解更多】可详细了解大会员服务内容,详情请致电咨询:400-108-6670,线下购买享优惠。'
+      },
+      {
+        text: '本次活动不支持作弊行为,涉嫌违法、违规参与活动的用户,剑鱼标讯将有权取消您的活动参与资格,并回收已获得的相关奖励,由于不可抗力因素等情况导致活动异常,剑鱼标讯将有权采取调整等措施。'
+      },
+      {
+        text: '法律许可范围内本次活动解释权归北京剑鱼信息技术有限公司所有。'
+      }
+    ]
+  },
+  computed: {
+    rate: function () {
+      var calcRate = (this.progress.current / this.progress.max) * 100
+      if (calcRate > 100) {
+        calcRate = 100
+      }
+      if (calcRate < 0) {
+        calcRate = 0
+      }
+      return calcRate
+    },
+    blinkTextShow: function () {
+      var anchorList = this.progress.anchorList
+      var rate = this.rate
+      var exist = false
+      for (var i = 0; i < anchorList.length; i++) {
+        if (rate === anchorList[i].rate) {
+          exist = true
+          break
+        }
+      }
+      return !exist
+    },
+    progressAnchorList: function () {
+      return this.progress.anchorList
+    },
+    lastTimeText: function () {
+      if (this.lastTimestamp > 0) {
+        var lastTimeConf = this.calcLastTimeDiff(this.lastTimestamp)
+        var days = lastTimeConf.days
+        var hours = lastTimeConf.hours
+        var minutes = lastTimeConf.minutes
+        var seconds = lastTimeConf.seconds
+        var hms = [this.add0(hours), this.add0(minutes), this.add0(seconds)].join(':')
+        if (days > 0) {
+          return days + '天 ' + hms
+        } else {
+          return hms
+        }
+        // return days + '天 ' + hms
+      } else {
+        return ''
+      }
+    },
+    yureSectionShow: function () {
+      return this.activeState === 'waiting' || this.activeState === 'yureing'
+    },
+    yureButtonShow: function () {
+      var lastTimeConf = this.calcLastTimeDiff(this.lastTimestamp)
+      var days = lastTimeConf.days
+      if (this.yureInfo.buttonText) {
+        return !(days < 1 && this.yureConf.total <= 0)
+      } else {
+        return false
+      }
+    },
+    calcYuReTopText: function () {
+      if (this.activeState === 'yureing') {
+        return '进行中'
+      } else if (this.activeState === 'waiting') {
+        return '未开始'
+      } else {
+        return '已结束'
+      }
+    },
+    onKeyReceiveShow: function () {
+      var arr = []
+      this.couponList.forEach(function (item) {
+        if (item.IsReceive === false && item.IsUser) {
+          arr.push(item)
+        }
+      })
+      return arr.length !== this.couponList.length
+    },
+    forbidClose: function () {
+      return this.dialog.type === 'over'
+    },
+    getScreenMax: function () {
+      return document.body.clientHeight < 600
+    }
+  },
+  created: function () {
+    this.platform = utils.isWeiXinBrowser ? 'wx' : 'app'
+    this.ajaxActiveStatus()
+    this.ajaxProgress()
+    this.getMissionList()
+  },
+  mounted: function () {
+    // this.calcPointList()
+    this.stickyTopEvents()
+    this.headerTransparent()
+  },
+  methods: {
+    add0: function (t) {
+      return t < 10 ? ('0' + t) : t
+    },
+    dialogShow: function (type, show) {
+      this.dialog.type = type
+      this.dialog.show = show
+    },
+    ajaxActiveStatus: function () {
+      var _this = this
+      $.ajax({
+        url: '/jyActivity/membershipDay/period',
+        type: 'post',
+        success: function (res) {
+          if (res.data) {
+            for (var key in _this.conf) {
+              _this.conf[key] = res.data[key]
+            }
+
+            if (Math.abs(initPageTime - res.data.now * 1000) > 5000) {
+              initPageTime = res.data.now
+            }
+            activeOverCheck(res.data.end * 1000, function () {
+              _this.dialogShow('over', true)
+            })
+            _this.initPageState()
+          }
+        },
+        complete: function () {
+          _this.getYuReCouponCount()
+          _this.getFuLi2CouponList()
+        }
+      })
+    },
+    initPageState: function () {
+      var state = this.checkActiveState()
+      var yureTextDOM = $('.timeline-item.yure .t-r-b-r')
+      if (state === 'yureing') {
+        this.startTopTimer()
+        yureTextDOM.text('进行中')
+      } else {
+        yureTextDOM.text('已结束')
+        if (state === 'activating') {
+          // 活动进行中
+        } else {
+
+        }
+      }
+    },
+    // 检查状态
+    checkActiveState: function (now) {
+      if (!now) {
+        now = Date.now()
+      }
+      var before = this.conf.before * 1000 // 预热开始
+      var start = this.conf.start * 1000 // 活动开始
+      var end = this.conf.end * 1000 // 活动结束
+      var stateArr = ['waiting', 'yureing', 'activating', 'ended']
+      var state = 'waiting'
+      if (now < before) {
+        state = stateArr[0] // 预热未开始
+      } else if (before <= now && now < start) {
+        state = stateArr[1] // 预热中
+      } else if (start <= now && now < end) {
+        state = stateArr[2] // 活动进行中
+      } else {
+        state = stateArr[3] // 活动已结束
+      }
+      this.activeState = state
+
+      // 计算时间间隔
+      var beforeStr = moment(before).format('M.DD')
+      var beforeStrEnd = moment(start - 1000).format('M.DD')
+      var startStr = moment(start).format('M.DD')
+      var endStr = moment(end - 1000).format('M.DD')
+
+      this.timeDuration.yure = [beforeStr, beforeStrEnd].join('-')
+      this.timeDuration.active = [startStr, endStr].join('-')
+
+      return state
+    },
+    // type=yure判断预热是否开始
+    // type=active 判断活动是否开始
+    activeNotStartToast: function (type) {
+      var state = this.checkActiveState()
+      type = type || 'active'
+      if (state === 'ended') {
+        this.$toast('活动已结束')
+      } else if (state === 'waiting') {
+        this.$toast('活动尚未开始,敬请期待')
+      } else {
+        if (type === 'yure') {
+          if (state === 'activating') {
+            // 预热已结束
+            this.$toast('预热已结束')
+          }
+        } else {
+          if (state === 'yureing') {
+            this.$toast('活动尚未开始,敬请期待')
+          }
+        }
+      }
+    },
+    startTopTimer: function () {
+      var _this = this
+      var start = this.conf.start * 1000
+      var timerId = setInterval(function () {
+        var current = Date.now()
+        if (_this.lastTimestamp < 0) {
+          clearInterval(timerId)
+        }
+        _this.lastTimestamp = start - current
+      }, 1000)
+    },
+    calcYuReText: function () {
+      var _this = this
+      var buttonText = ''
+      var tipText = ''
+      var buttonDisabled = true
+      if (this.yureInfo.timerId) {
+        clearInterval(this.yureInfo.timerId)
+      }
+      if (this.activeState === 'yureing') {
+        // 当天时间
+        var todayString = new Date().pattern('yyyy/MM/dd')
+        // 当领券开始时间
+        var yureCouponStartTime = [todayString, this.conf.clock].join(' ')
+        var yureCouponStartStamp = +new Date(yureCouponStartTime)
+        // 计算倒计时
+        var diff = yureCouponStartStamp - Date.now()
+        if (diff > 0) {
+          // 预热当天未开始抢券
+          buttonDisabled = true
+          // 计算小时
+          if (this.conf.clock) {
+            var clockArr = this.conf.clock.split(':')
+            buttonText = '今日'+ clockArr[0] +'点开抢'
+          } else {
+            buttonText = '今日10点开抢'
+          }
+          // 创建定时器刷新倒计时
+          this.yureInfo.timerId = setInterval(function () {
+            var d = yureCouponStartStamp - Date.now()
+            var obj = _this.calcLastTimeDiff(d)
+            if (d <= 0) {
+              clearInterval(_this.yureInfo.timerId)
+              _this.calcYuReText()
+            } else {
+              // 计算倒计时
+              tipText = [_this.add0(obj.hours), _this.add0(obj.minutes), _this.add0(obj.seconds)].join(':')
+              _this.yureInfo.tipText = tipText
+            }
+          }, 1000)
+        } else {
+          if (this.yureConf.got) {
+            // 已领取过
+            buttonDisabled = false
+            buttonText = '去查看'
+            tipText = '已领取成功'
+          } else {
+            buttonDisabled = this.yureConf.total <= 0
+            // 券是否有剩余
+            if (this.yureConf.total > 0) {
+              buttonText = '点击免费领'
+              tipText = '今日还剩<span class="num">' + this.yureConf.total + '</span>份'
+            } else {
+              // 今日券领完了
+              buttonText = '今天已抢完'
+              tipText = '今天已经抢完啦~明天再来吧'
+            }
+          }
+        }
+      } else {
+        // 预热未开始或者预热结束
+      }
+
+      this.yureInfo.buttonDisabled = buttonDisabled
+      this.yureInfo.buttonText = buttonText
+      this.yureInfo.tipText = tipText
+    },
+    calcLastTimeDiff: function (timestamp) {
+      var diff = moment.duration(Math.abs(timestamp))
+      var days = diff.days()
+      var hours = diff.hours()
+      var minutes = diff.minutes()
+      var seconds = diff.seconds()
+      return {
+        days: days,
+        hours: hours,
+        minutes: minutes,
+        seconds: seconds
+      }
+    },
+    // 预热优惠券数量查询
+    getYuReCouponCount: function () {
+      var _this = this
+      $.ajax({
+        url: '/jyActivity/membershipDay/getDailyBoonDetail',
+        type: 'post',
+        success: function (res) {
+          if (res.data) {
+            _this.yureConf.got = res.data.got || false
+            _this.yureConf.total = res.data.total || 0
+            _this.calcYuReText()
+          }
+        }
+      })
+    },
+    receiveYuReCoupon: function () {
+      if (this.yureInfo.buttonDisabled) {
+
+      } else {
+        this.receiveYuReCouponAjax()
+      }
+      if (this.yureInfo.buttonDisabled) {
+        this.$toast('活动尚未开始,敬请期待')
+      } else if (this.yureInfo.buttonText === '去查看') {
+        // 领过了,跳转订单列表
+        this.toOrderPage()
+      } else {
+        // 没领过
+        this.receiveYuReCouponAjax()
+      }
+    },
+    // 领取预热优惠券
+    receiveYuReCouponAjax: function () {
+      var _this = this
+      $.ajax({
+        url: '/jyActivity/membershipDay/getDailyBoonSVip',
+        type: 'post',
+        success: function (res) {
+          if (res.data) {
+            _this.getYuReCouponCount()
+            _this.$toast('领取成功')
+            // 刷新我的奖励列表
+            _this.getMissionList()
+          }
+        }
+      })
+    },
+    receiveActiveButtonText: function (item) {
+      if (item.IsReceive) {
+        return '立即领取'
+      } else {
+        if (item.IsUser) {
+          return '去使用'
+        } else {
+          return '已使用'
+        }
+      }
+    },
+    receiveActiveCoupon: function (coupons) {
+      if (this.activeState !== 'activating') {
+        return this.activeNotStartToast()
+      }
+      if (coupons.length === 0) return
+      if (coupons.length === 1) {
+        var item = coupons[0]
+        if (!item.IsReceive && item.IsUser) {
+          this.toBuyVip()
+        }
+        return
+      }
+      var idArr = []
+      coupons.forEach(function (item) {
+        if (item.IsReceive) {
+          idArr.push(item.LotteryIdStr)
+        }
+      })
+      this.receiveActiveCouponAjax(idArr)
+    },
+    // 领取活动优惠券
+    receiveActiveCouponAjax: function (ids) {
+      if (ids.length === 0) return
+      var _this = this
+      $.ajax({
+        url: '/jyActivity/membershipDay/getLottery',
+        type: 'post',
+        contentType: 'application/json',
+        data: JSON.stringify({
+          lotteryIds: ids.join(',')
+        }),
+        success: function (res) {
+          if (res.data) {
+            _this.couponList.forEach(function (item) {
+              if (ids.indexOf(item.LotteryIdStr) !== -1) {
+                item.IsReceive = false
+              }
+            })
+            _this.$toast('领取成功')
+            // 刷新我的奖励列表
+            _this.getMissionList()
+          }
+        }
+      })
+    },
+    addTipText: function (list) {
+      var prefix = '超级订阅'
+      var priceArr = [
+        {
+          price: 38,
+          text: '/月/省'
+        },
+        {
+          price: 99,
+          text: '/季/省'
+        },
+        {
+          price: 380,
+          text: '/年/省'
+        },
+        {
+          price: 599,
+          text: '/月/全国'
+        },
+      ]
+      var arr = list.sort(function (a, b) {
+        return a.Reduce - b.Reduce
+      })
+      list.forEach(function (item) {
+        var reduce = item.Reduce
+        var full = item.Full
+        for (var i = 0; i < priceArr.length; i++) {
+          if (priceArr[i].price - full >= 0) {
+            var pay = priceArr[i].price - reduce
+            item.tipText = prefix + priceArr[i].text + ':券后' + pay + '元'
+            break
+          }
+        }
+      })
+      return arr
+    },
+    // 获取福利2优惠券列表
+    getFuLi2CouponList: function () {
+      var _this = this
+      $.ajax({
+        url: '/jyActivity/membershipDay/lotteryList',
+        type: 'post',
+        success: function (res) {
+          if (res.data) {
+            _this.couponList = _this.addTipText(res.data) || []
+            // 刷新我的奖励列表
+            _this.getMissionList()
+          }
+        }
+      })
+    },
+    calcPointList: function () {
+      var dom = this.$refs.missions
+      window.points = new RandomCoordinate({
+        el: dom,
+        total: this.missionsList.length,
+        pointSize: new Map(142, 160)
+      })
+      var pointList = points.pointCoordList
+      for (var i = 0; i < this.missionsList.length; i++) {
+        this.missionsList[i].x = pointList[i].x
+        this.missionsList[i].y = pointList[i].y
+      }
+    },
+    leaveCanvas: function (item) {
+      var rootFontSize = RootNodeFontSize()
+      var dom = $('.mission-list-item.' + item.id)
+      dom.removeClass('floating')
+      var baseX = -1.2 * rootFontSize
+      var baseY = 0.6 * rootFontSize
+
+      // 终点坐标
+      var current = {
+        x: baseX + $('.progress-bar-content').width(),
+        y: baseY + $('.mission-list').height() - $('.blink-point').height() / 2
+      }
+
+      item.x = current.x / rootFontSize
+      item.y = current.y / rootFontSize
+      this.$nextTick(function () {
+        dom.addClass('exit')
+      })
+    },
+    onClickListItem: function (item) {
+      if (item.icon === 'jy-svip') {
+        this.toOrderPage()
+      } else if (item.icon === 'jy-coin') {
+        location.href = '/page_points_mobile/list'
+      } else {
+        // 跳转我的奖券
+        if (utils.isWeiXinBrowser) {
+          location.href = '/weixin/frontPage/coupon/free/myCoupon'
+        } else {
+          location.href = '/jyapp/frontPage/coupon/free/myCoupon'
+        }
+        // this.toBuyVip()
+      }
+    },
+    onClickReceive: function (type, item) {
+      if (this.activeState !== 'activating') {
+        // this.$toast('活动尚未开始,敬请期待')
+        return this.activeNotStartToast()
+      }
+      if (item.className === 'received') return
+      var status = false
+      if (type === 'schedule') {
+        if (item.className === 'wait') {
+          status = true
+        } else {
+          var text = '尚未达到领取条件,无法领取'
+          switch (item.id) {
+            // 800
+            case this.progressAnchorList[1].id: {
+              text = '尚未达到'+ this.progressAnchorList[1].id +'剑鱼币,无法领取'
+              break
+            }
+            // 1500
+            case this.progressAnchorList[2].id: {
+              text = '尚未达到'+ this.progressAnchorList[2].id +'剑鱼币,无法领取'
+              break
+            }
+          }
+          return this.$toast(text, 1500)
+        }
+      } else if (type === 'mission' && item.complete) {
+        status = true
+      }
+      if (!status) {
+        var _this = this
+        switch (item.id) {
+          case 'buyvip': {
+            this.toBuyVip()
+            break
+          }
+          case 'invite': {
+            if (utils.isWeiXinBrowser) {
+              location.href = '/weixin/frontPage/share/sess/index'
+            } else {
+              location.href = '/jyapp/frontPage/share/sess/index'
+            }
+            break
+          }
+          case 'share': {
+            // 分享----------
+            // _this.scrollTo('.copy-share-container')
+            break
+          }
+        }
+        return
+      }
+      var _this = this
+      if (type === 'mission') {
+        this.leaveCanvas(item)
+      }
+      this.ajaxReceive({ type: type, value: item.id }, function (result, msg) {
+        if (result) {
+          switch (item.id) {
+            case 'buyvip':
+            case 'invite':
+            case 'share': {
+              _this.$toast('已成功领取' + item.num + '剑鱼币', 1500)
+              break
+            }
+            case '800': {
+              _this.dialogShow('success', true)
+              break
+            }
+            case '1500': {
+              _this.dialogShow('success', true)
+              break
+            }
+          }
+          _this.ajaxActiveStatus()
+          _this.ajaxProgress()
+          _this.getMissionList()
+        } else {
+          _this.$toast(msg, 1500)
+        }
+      })
+    },
+    ajaxReceive: function (data, callback) {
+      var _this = this
+      $.ajax({
+        url: '/jyActivity/membershipDay/receive',
+        type: 'post',
+        contentType: 'application/json',
+        data: JSON.stringify(data),
+        success: function (res) {
+          callback(res.data, res.error_msg)
+          // 刷新我的奖励列表
+          _this.getMissionList()
+        }
+      })
+    },
+    ajaxProgress: function () {
+      var _this = this
+      $.ajax({
+        url: '/jyActivity/membershipDay/schedule',
+        type: 'post',
+        success: function (res) {
+          if (res.error_code === 0 && res.data) {
+            _this.progress.current = res.data.nowNum
+
+            _this.missionsList[0].complete = res.data.missions.buyvip !== 0
+            _this.missionsList[1].complete = res.data.missions.invite !== 0
+            _this.missionsList[2].complete = res.data.missions.share !== 0
+
+            _this.missionsList[0].hide = res.data.missions.buyvip === -1
+            _this.missionsList[1].hide = res.data.missions.invite === -1
+            _this.missionsList[2].hide = res.data.missions.share === -1
+
+            var anchorStatus = {
+              1: 'wait',
+              0: 'unreceived',
+              '-1': 'received',
+            }
+            var imgStatus = {
+              1: 'unreceived',
+              0: 'unreceived',
+              '-1': 'received',
+            }
+
+            _this.progress.anchorList[1].className = anchorStatus[res.data.schedule['800']]
+            _this.progress.anchorList[2].className = anchorStatus[res.data.schedule['1500']]
+
+            _this.progress.anchorList[1].pointImg = imgStatus[res.data.schedule['800']]
+            _this.progress.anchorList[2].pointImg = imgStatus[res.data.schedule['1500']]
+          }
+        }
+      })
+    },
+    getMissionList: function () {
+      var _this = this
+      $.ajax({
+        url: '/jyActivity/myAward/awardlist',
+        type: 'post',
+        contentType: 'application/json',
+        data: JSON.stringify({
+          code: 'membershipDay',
+          pageSize: 10,
+          pageNum: 0
+        }),
+        success: function (res) {
+          if (res.error_code === 0 && res.data) {
+            if (res.data.list && typeof res.data.list.map === 'function') {
+              _this.rewardList = res.data.list.map(function (v) {
+                var icon = ''
+                if (v.award.indexOf('剑鱼币') > -1) {
+                  icon = 'jy-coin'
+                } else if (v.award.indexOf('订阅') > -1) {
+                  icon = 'jy-svip'
+                } else {
+                  icon = 'jy-coupon'
+                }
+                return {
+                  id: v._id,
+                  icon: icon,
+                  rewardText: v.award,
+                  receiveTime: new Date(v.date * 1000).pattern('yyyy-MM-dd HH:mm:ss'),
+                  receiveFrom: v.getway
+                }
+              })
+            }
+          }
+        }
+      })
+    },
+    receiveFuli3: function () {
+      if (this.activeState !== 'activating') {
+        return this.activeNotStartToast()
+      }
+      if (utils.isWeiXinBrowser) {
+        location.href = '/weixin/frontPage/bigmember/free/perfect_info?source=super_membership_day'
+      } else {
+        location.href = '/jyapp/frontPage/bigmember/free/perfect_info?source=super_membership_day'
+      }
+    },
+    doCopy: function () {
+      if (this.activeState === 'activating') {
+        var _this = this
+        $.ajax({
+          url: '/jyActivity/membershipDay/doShare',
+          type: 'post',
+          success: function (res) {
+            if (res.data) {
+              _this.$toast('复制成功')
+              _this.ajaxProgress()
+            }
+          }
+        })
+      } else {
+        // this.$toast('活动尚未开始,敬请期待')
+        this.activeNotStartToast()
+      }
+      this.copyText('快来和我一起参与吧!剑鱼超级会员节,百万补贴限量抢,快速获取商机信息》\n' + this.copyLinkText)
+    },
+    copyText: function (text) {
+      const input = document.createElement('textarea') // js创建一个input输入框
+      input.value = text // 将需要复制的文本赋值到创建的input输入框中
+      document.body.appendChild(input) // 将输入框暂时创建到实例里面
+      input.select() // 选中输入框中的内容
+      document.execCommand('copy') // 执行复制操作
+      document.body.removeChild(input) // 最后删除实例中临时创建的input输入框,完成复制操作
+    },
+    scrollTo: function (className) {
+      setTimeout(function () {
+        var offsetTop = $(className)[0].offsetTop
+        $('#main-app').scrollTop(offsetTop)
+      }, 100)
+    },
+    stickyTopEvents: function () {
+      var _this = this
+      var fixedTop = $('.fixed-top.top-timeline')
+      var scrollDOM = $('#main-app')
+      var height = $('.header-banner').height()
+      var showHide = function () {
+        var scrollTop = scrollDOM.scrollTop()
+        if (scrollTop > height) {
+          fixedTop.show()
+        } else {
+          fixedTop.hide()
+        }
+      }
+      showHide()
+      scrollDOM.on('scroll', function () {
+        showHide()
+      })
+      fixedTop.on('click', '.timeline-item', function (e) {
+        $(e.currentTarget).addClass('active').siblings().removeClass('active')
+        var className = $(e.currentTarget).attr('data-s-class')
+        _this.scrollTo('.' + className)
+      })
+    },
+    headerTransparent: function () {
+      if (utils.isWeiXinBrowser) return
+      $('#main-app').on('scroll', function () {
+        var headerDOM = $('.j-header.jy-app-header')
+        var scrollTop = this.scrollTop
+
+        // 是否有header-transparent这个类名
+        var hasClassT = headerDOM.hasClass('transparent-header')
+
+        if (scrollTop >= 75) {
+          if (!hasClassT) return
+          headerDOM.removeClass('transparent-header')
+        }else {
+          if (hasClassT) return
+          headerDOM.addClass('transparent-header')
+        }
+      })
+    },
+    toOrderPage: function () {
+      if (utils.isWeiXinBrowser) {
+        location.href = '/weixin/pay/toMyWxOrder?active=0'
+      } else {
+        location.href = '/jyapp/front/myOrder/toMyOrder?active=0'
+      }
+    },
+    toMemberPage: function () {
+      if (utils.isWeiXinBrowser) {
+        location.href = '/big/wx/page/landingPage'
+      } else {
+        location.href = '/jyapp/big/page/landingPage'
+      }
+    },
+    toBuyVip: function () {
+      location.href = '/jy_mobile/common/order/create/svip?type=buy'
+    }
+  }
+})

+ 314 - 0
src/web/staticres/common-module/active/2022.7/task-common.css

@@ -0,0 +1,314 @@
+.j-icon-bg {
+  display: block;
+  width: 24px;
+  height: 24px;
+  background-repeat: no-repeat;
+  background-size: contain;
+}
+.icon-bg-jy-coin {
+  background-image: url(/common-module/active/2022.5.20/jianyubi@2x.png);
+}
+.icon-bg-jy-svip {
+  background-image: url(/common-module/active/2022.5.20/chaojidingyue@2x.png);
+}
+.icon-bg-jy-coupon {
+  background-image: url(/common-module/active/2022.7/icon-coupon@2x.png);
+}
+.header-banner > img,
+.point-img > img {
+  display: block;
+  width: 100%;
+}
+
+.header-banner {
+  position: relative;
+}
+
+.floating {
+  animation: floating 1.3s ease-in-out 1.3s infinite alternate;
+  transition: left,right,top,bottom 1.3s ease;
+}
+.floating.delay-100 {
+  /* animation-delay: 0.1s; */
+}
+.floating.delay-300 {
+  /* animation-delay: 0.3s; */
+}
+
+@keyframes floating {
+  from {
+    transform: translate(0, 0);
+  }
+  to {
+    transform: translate(0, 10px);
+  }
+}
+
+.mission-list {
+  display: flex;
+  align-items: center;
+  position: absolute;
+  left: 50%;
+  bottom: -0.6rem;
+  z-index: 2;
+  width: 86%;
+  height: 5rem;
+  transform: translateX(-50%);
+}
+.mission-list-item {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  position: absolute;
+  left: 0;
+  top: 0;
+  transition: all 0.8s cubic-bezier(0, 0, 0.2, 1);
+  transform: scale(1);
+  z-index: 2;
+}
+.mission-list-item.exit {
+  transform: scale(0);
+}
+.mission-list-item.hide {
+  display: none!important;
+}
+
+.text-gradient-red {
+  background-image: linear-gradient(90deg, #FE542F 0%, #F01313 100%);
+  -webkit-background-clip: text;
+  -webkit-text-fill-color: transparent;
+}
+
+.m-list-item-bg {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: space-between;
+  padding: .26rem 0;
+  width: 1.6rem;
+  height: 1.6rem;
+  background-image: url(/common-module/active/2022.5.20/bubble-2@2x.png);
+  background-repeat: no-repeat;
+  background-size: contain;
+}
+.mission-list-item.complete .text,
+.mission-list-item.complete .num {
+  opacity: 1;
+}
+.mission-list-item.complete .m-list-item-bg {
+  background-image: url(/common-module/active/2022.5.20/bubble-1@2x.png);
+}
+.m-list-item-bg .num {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  font-size: .32rem;
+  font-weight: bold;
+  color: #CF1627;
+  line-height: .4rem;
+  opacity: 0.6;
+}
+.num .num-add {
+  font-size: .24rem;
+  font-weight: 400;
+}
+.m-list-item-bg .text {
+  font-size: .2rem;
+  color: #CF1627;
+  line-height: .24rem;
+  opacity: 0.6;
+}
+.m-list-item-bg .button {
+  position: relative;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  min-width: 0.8rem;
+  margin-top: .04rem;
+  padding: .04rem .08rem;
+  font-size: .16rem;
+  color: #fff;
+  line-height: .2rem;
+  background: linear-gradient(180deg, #F84B4B 0%, #E4192B 100%);
+  border-image: linear-gradient(180deg, rgba(255, 216, 216, 0), rgba(255, 216, 216, 1)) 1 1;
+  border-radius: .16rem;
+  cursor: pointer;
+}
+.m-list-item-bg .button::after {
+  /* content: ''; */
+  position: absolute;
+  top: -0.04rem;
+  bottom: -0.04rem;
+  left: -0.04rem;
+  right: -0.04rem;
+  background: linear-gradient(180deg, rgba(255, 216, 216, 0), rgba(255, 216, 216, 1));
+  z-index: -1;
+  border-radius: 16rem;
+}
+.m-list-item-text {
+  font-size: .2rem;
+  font-weight: 700;
+  color: #CF1627;
+}
+
+.content-container {
+  background: linear-gradient(180deg, #FF993B 0%, #D24A2A 90%);
+}
+
+.progress-bar-container {
+  padding: 1rem 0 .4rem;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+.progress-bar-label {
+  margin-right: 20px;
+  font-size: 16px;
+  line-height: 20px;
+  color: #fff;
+}
+.progress-bar {
+  position: relative;
+  width: 92%;
+  height: .28rem;
+  background: #FEC285;
+  box-shadow: inset 0px 6px 8px 1px rgba(255, 255, 255, 0.4);
+  border-radius: .28rem;
+  background-color: rgba(255, 255, 255, 0.6);
+  z-index: 1;
+}
+.progress-bar-content {
+  position: relative;
+  height: 100%;
+  min-width: .36rem;
+  background: linear-gradient(270deg, #FFFFFF 20%, rgba(255, 255, 255, 0) 100%);
+  border-radius: .4rem;
+  z-index: 2;
+  transition: all 0.8s cubic-bezier(0.15, 0.85, 1, 1);
+}
+.blink-point {
+  position: absolute;
+  top: 50%;
+  right: 0;
+  transform: translate(0,-50%);
+  width: .44rem;
+  height: .44rem;
+  border-radius: 50%;
+  background-color: rgba(255, 255, 255, 0.9);
+  filter: blur(8px) drop-shadow(0 0 2px rgba(255, 255, 255, 0.8)) drop-shadow(0 0 8px rgba(255, 255, 255, 0.9)) drop-shadow(0 0 16px rgba(255, 255, 255, 1));
+  z-index: 3;
+}
+.blink-point {
+  width: 1.2rem;
+  height: 1.2rem;
+  transform: translate(40%,-50%);
+  background-color: transparent;
+  background-image: url(/common-module/active/2022.5.20/blink-point.png);
+  background-repeat: no-repeat;
+  background-size: contain;
+  filter: none;
+}
+.anchor {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: space-between;
+  position: absolute;
+  top: -0.6rem;
+  left: 0;
+  color: #fff;
+  transform: translateX(-60%);
+  z-index: 4;
+  transition: all 1s cubic-bezier(0.15, 0.85, 1, 1);
+}
+.anchor.first {
+  transform: none;
+}
+.anchor.last .anchor-text {
+  transform: translateX(-20%);
+}
+.anchor.wait .anchor-tip-text {
+  color: #fff;
+}
+.blink-point-text {
+  position: absolute;
+  right: 0;
+  top: -0.36rem;
+  transform: translate(40%,-100%);
+}
+.anchor-text {
+  font-size: .2rem;
+  line-height: .24rem;
+  color: #fff;
+  white-space: nowrap;
+}
+.point-img {
+  margin-top: .16rem;
+  width: .72rem;
+  cursor: pointer;
+}
+.anchor-tip-text {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  font-size: 14px;
+  line-height: 16px;
+  font-weight: 700;
+  color: rgba(255, 255, 255, 0.6);
+  cursor: pointer;
+  background-size: contain;
+}
+.progress-action-list {
+  padding: 0 .24rem;
+  display: flex;
+  flex-wrap: wrap;
+  align-items: center;
+  justify-content: space-between;
+}
+.progress-action-button {
+  position: relative;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  width: 45%;
+  padding: .3rem .6rem;
+  font-size: .24rem;
+  line-height: .28rem;
+  color: #fff;
+  background: linear-gradient(180deg, #F45600 7%, #F14904 100%);
+  box-shadow: inset 2px 3px 4px 1px rgba(255, 255, 255, 0.7);
+  border-radius: .5rem;
+  white-space: nowrap;
+}
+.progress-action-button[disabled] {
+  color: rgba(255, 255, 255, 0.6);
+  background: #F85630;
+  box-shadow: none;
+}
+.progress-action-button[disabled].pointer::after {
+  content: unset;
+}
+.progress-action-button.pointer::after {
+  content: '';
+  position: absolute;
+  left: 70%;
+  bottom: -0.8rem;
+  display: block;
+  width: 1.6rem;
+  height: 1.6rem;
+  background-image: url(/common-module/active/2022.5.20/pointer@2x.png);
+  background-repeat: no-repeat;
+  background-size: contain;
+  transform: translate(-50%, 0);
+  animation: pointer 1.3s ease-out 1.3s infinite alternate;
+}
+@keyframes pointer {
+  from {
+    transform: translate(-50%, 0) scale(1);
+  }
+  to {
+    transform: translate(-50%, -.1rem) scale(1.3);
+  }
+}

BIN
src/web/staticres/common-module/active/2022.7/title-fuli1@2x.png


BIN
src/web/staticres/common-module/active/2022.7/title-fuli2@2x.png


BIN
src/web/staticres/common-module/active/2022.7/title-fuli3@2x.png


BIN
src/web/staticres/common-module/active/2022.7/title-yure@2x.png


+ 4 - 0
src/web/staticres/common-module/public/js/app-share.js

@@ -0,0 +1,4 @@
+// 基于van-share-sheet的封装
+var appShareSheet = {
+
+}

+ 604 - 0
src/web/staticres/frontRouter/pc/activity/css/task-202207.css

@@ -0,0 +1,604 @@
+.content-container img,
+.header-banner img,
+.point-img img {
+  display: block;
+  width: 100%;
+}
+.section:not(:first-of-type, :last-of-type) {
+  margin-bottom: 80px;
+}
+.header-banner {
+  position: relative;
+}
+.header-strategy {
+  position: relative;
+  margin-top: -2px;
+  background-color: #D10F06;
+  z-index: 1;
+}
+
+.content-container {
+  padding: 64px 0;
+  background: linear-gradient(127deg, #FF6A63 0%, #D54841 100%);
+}
+
+.section .section-header {
+  margin-bottom: 40px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+.section .section-content {
+  position: relative;
+}
+.section .section-footer {
+  margin-top: 40px;
+}
+
+.section .section-header-button {
+  width: 728px;
+}
+
+.section-button {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  font-size: 20px;
+  font-weight: bold;
+  color: #E8100D;
+  line-height: 23px;
+  background-color: transparent;
+  background-repeat: no-repeat;
+  background-size: contain;
+  cursor: pointer;
+}
+.section-button:disabled {
+  color: #FF7876;
+}
+
+.section-button.button-large {
+  width: 342px;
+  height: 56px;
+  background-image: url(/frontRouter/pc/activity/image/202207/button-large@2x.png);
+  background-size: 100% 100%;
+}
+.section-button.button-middle {
+  width: 240px;
+  height: 60px;
+  background-image: url(/frontRouter/pc/activity/image/202207/button-middle@2x.png);
+  background-size: 100% 100%;
+}
+.section-button.button-small {
+  width: 180px;
+  height: 55px;
+  background-image: url(/frontRouter/pc/activity/image/202207/button-small@2x.png);
+  background-size: 100% 100%;
+}
+
+.section-yure .content-info {
+  position: absolute;
+  left: 50%;
+  bottom: 120px;
+  transform: translateX(-50%);
+  color: #fff;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+}
+.section-yure .c-info-text {
+  font-size: 42px;
+  font-family: 'YouSheBiaoTiHei';
+  line-height: 50px;
+  text-shadow: 2px 3px 0px #CF1627;
+}
+.section-yure .c-info-text .num {
+  font-size: 96px;
+  line-height: 114px;
+}
+
+.section-more-activities .header-text {
+  width: 526px;
+}
+
+.section-fuli1 .coupon-list {
+  display: flex;
+  flex-wrap: wrap;
+}
+.section-fuli1 .coupon-item {
+  margin: 8px 0;
+  margin-right: 32px;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  width: 276px;
+  height: 277px;
+  font-size: 16px;
+  color: #E80E0D;
+  background-image: url(/common-module/active/2022.7/coupon-bg@2x.png);
+  background-repeat: no-repeat;
+  background-size: contain;
+  text-align: center;
+}
+.section-fuli1 .coupon-item:nth-of-type(4n) {
+  margin-right: 0;
+}
+.coupon-item .coupon-title {
+  line-height: 56px;
+}
+.coupon-item .coupon-value .num {
+  font-size: 96px;
+  line-height: 86px;
+  font-weight: bold;
+}
+.coupon-item .section-button {
+  margin-top: 30px;
+}
+.coupon-item .coupon-text {
+  margin: 16px;
+  font-size: 14px;
+  color: #fff;
+  white-space: nowrap;
+}
+.section-fuli1 .section-footer {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+.m-list-item-text {
+  font-size: 16px;
+  color: #fff;
+}
+
+.section-fuli2 .mission-list {
+  /* background-color: pink; */
+}
+.section-fuli2 .mission-list-img {
+  width: 90%;
+  position: absolute;
+  top: -60%;
+  left: 50%;
+  transform: translateX(-50%);
+  z-index: 1;
+}
+
+.section-fuli3 .section-header {
+  margin-bottom: 56px;
+}
+.section-fuli3 .entniche-card-list {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+}
+.section-fuli3 .entniche-card-item {
+  width: 584px;
+  height: 430px;
+  background-repeat: no-repeat;
+  background-size: contain;
+}
+.entniche-card-item.shangji {
+  background-image: url(/frontRouter/pc/activity/image/202207/entniche-shangji@2x.png);
+}
+.entniche-card-item.zhuanjia {
+  background-image: url(/frontRouter/pc/activity/image/202207/entniche-zhuanjia@2x.png);
+}
+.section-fuli3 .button-group {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+.section-fuli3 .learn-more {
+  margin-right: 32px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  width: 240px;
+  height: 48px;
+  border-radius: 25px;
+  border: 1px solid #fff;
+  color: #fff;
+}
+.section-fuli3 .text {
+  margin: 34px 0 80px;
+  font-size: 18px;
+  line-height: 26px;
+  color: #fff;
+  text-align: center;
+}
+
+.activity-rules .section-header-text {
+  width: 207px;
+}
+.activity-rules .rules-list {
+  padding: 38px;
+}
+.rules-item {
+  display: flex;
+  margin-bottom: 6px;
+  font-size: 18px;
+  color: #fff;
+  line-height: 28px;
+}
+.rules-item:last-of-type {
+  margin-bottom: 0;
+}
+.rule-index {
+  margin-right: 6px;
+}
+.rule-text {
+  flex: 1;
+}
+.activity-rules .section-footer {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  padding-bottom: 160px;
+}
+.activity-rules .footer-text {
+  margin: 40px 0 24px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  width: 713px;
+}
+.activity-rules  .copy-share-container {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  color: #fff;
+}
+.copy-share-container .label-text {
+  font-size: 16px;
+  line-height: 20px;
+}
+.copy-share-container .label-bold {
+  font-weight: bold;
+}
+.copy-share-container .content {
+  margin-left: 8px;
+  width: 480px;
+  height: 48px;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  font-size: 14px;
+  line-height: 22px;
+  border-radius: 30px;
+  border: 1px solid #E3E4E5;
+}
+.copy-share-container .content-text {
+  padding: 0 20px;
+  flex: 1;
+}
+.copy-share-container .button-small {
+  height: 64px;
+}
+
+.fixed-top {
+  position: fixed;
+  top: 64px;
+  left: 0;
+  width: 100%;
+  z-index: 2;
+}
+.fixed-right {
+  position: fixed;
+  top: 200px;
+  right: 16px;
+  display: flex;
+  flex-direction: column;
+  z-index: 2;
+}
+.fixed-action-button {
+  margin-bottom: 22px;
+  color: #fff;
+  width: 67px;
+  height: 77px;
+  font-size: 16px;
+  line-height: 20px;
+  background-color: transparent;
+  background-image: url(/common-module/active/2022.7/float-button-bg@2x.png);
+  background-repeat: no-repeat;
+  background-size: contain;
+}
+
+
+.reward-section .el-dialog {
+  border-radius: 25px;
+  background: linear-gradient(to bottom, #FBDB9F 0%, #FFECD7 50%, #FBDB9F 100%);
+}
+.reward-section .el-dialog__header {
+  padding: 28px 24px 12px;
+  text-align: center;
+}
+.reward-section .el-dialog__title {
+  color: #F01313;
+  font-size: 24px;
+  font-weight: bold;
+  line-height: 28px;
+}
+.reward-section .el-dialog__close {
+  font-size: 26px;
+  font-weight: bold;
+  color: #F01313!important;
+}
+.reward-section .el-dialog__body {
+  padding-left: 24px;
+  padding-right: 24px;
+}
+.reward-card {
+  padding: 8px 0;
+  background: #FDF0E1;
+  border-radius: 20px;
+}
+.reward-list-header {
+  font-size: 20px;
+  font-weight: bold;
+  color: #1D1D1D;
+  line-height: 22px;
+}
+.reward-list {
+  padding: 6px 0;
+}
+.reward-card .j-icon {
+  width: 48px;
+  height: 48px;
+}
+.reward-card .tr {
+  display: flex;
+}
+.reward-card .td {
+  display: flex;
+  align-items: center;
+  padding: 16px;
+}
+.reward-card .tr .td:nth-of-type(1),
+.reward-card .tr .td:nth-of-type(2) {
+  flex: 5;
+}
+.reward-card .tr .td:nth-of-type(3) {
+  flex: 4;
+}
+.reward-card .tr .td:nth-of-type(4) {
+  flex: 2;
+}
+.reward-card .r-l-i-name .j-icon {
+  margin-right: 4px;
+}
+.table-line {
+  height: 5px;
+  width: 100%;
+  background: #F7A661;
+  box-shadow: inset 0px 6px 8px 1px rgba(255, 255, 255, 0.4);
+  border-radius: 20px;
+}
+.reward-action-button {
+  padding: 2px 12px;
+  color: #fff;
+  font-size: 16px;
+  line-height: 24px;
+  background: linear-gradient(176deg, #FA8920 0%, #FB4D27 65%, #DD1515 100%);
+  white-space: nowrap;
+  border-radius: 14px;
+}
+.reward-empty {
+  font-size: 16px;
+  font-weight: 400;
+  color: #AAAAAA;
+  line-height: 24px;
+  text-align: center;
+  padding-top: 78px;
+  padding-bottom: 67px;
+}
+
+.top-timeline {
+  height: 64px;
+  background-color: #fff;
+}
+.timeline-list {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  height: 100%;
+}
+.timeline-item {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  flex: 1;
+  height: 100%;
+  font-size: 14px;
+  color: #171826;
+  cursor: pointer;
+}
+.timeline-item:not(:last-of-type) {
+  border-right: 1px solid #ececec;
+}
+.timeline-item .t-left {
+  margin-right: 16px;
+  font-size: 20px;
+  line-height: 22px;
+}
+.timeline-item .t-r-top {
+  line-height: 16px;
+}
+.timeline-item .t-r-bottom {
+  margin-top: 6px;
+  display: flex;
+  align-items: center;
+  line-height: 20px;
+  color: #5E5B5B;
+}
+/* 第一种类型 */
+.timeline-item .t-r-b-r {
+  margin-left: 8px;
+  color: #E30101;
+  font-weight: bold;
+}
+/* 第二种 */
+.timeline-item .t-r-b-l2 {
+  color: #E30101;
+}
+.timeline-item .t-r-b-r2 {
+  margin-left: 8px;
+  padding: 1px 8px;
+  border-radius: 20px;
+  color: #fff;
+  background: #E30101;
+  box-shadow: 1px 0px 0px 1px rgba(0,0,0,0.08);
+}
+
+.timeline-item.active {
+  color: #fff;
+  background-color: #E30101;
+}
+/* 高亮1 */
+.timeline-item.active .t-r-b-l,
+.timeline-item.active .t-r-b-l2,
+.timeline-item.active .t-r-b-r {
+  color: #fff;
+}
+/* 高亮2 */
+.timeline-item.active .t-r-b-r2 {
+  border-radius: 20px;
+  color: #E30101;
+  background: #fff;
+  box-shadow: 1px 0px 0px 1px rgba(0,0,0,0.08);
+}
+
+
+
+#active-tip-modal .modal-dialog {
+  display: none;
+}
+#active-tip-modal[data-modal-type='success'] .modal-dialog.active-tip--success,
+#active-tip-modal[data-modal-type='over'] .modal-dialog.active-tip--over,
+#active-tip-modal[data-modal-type='code'] .modal-dialog.active-tip--code {
+  display: flex;
+}
+
+.active-tip--success,
+.active-tip--over,
+.active-tip--code {
+  position: relative;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  width: 303px;
+  height: 400px;
+  margin: 0 auto;
+  top: calc(50% - 200px);
+  border-radius: 12px;
+  overflow: hidden;
+}
+.active-tip--success button,
+.active-tip--over button {
+  width: 231px;
+  height: 48px;
+  background: linear-gradient(180deg, #FFCC66 0%, #FFECC5 100%);
+  font-size: 16px;
+  font-weight: 500;
+  color: #171826;
+  border-radius: 24px;
+}
+
+.active-tip--success .bg-image,
+.active-tip--code .bg-image {
+  position: absolute;
+  z-index: -1;
+  width: 100%;
+}
+
+.active-tip--success p span {
+  display: inline-block;
+  margin-top: 11px;
+  margin-bottom: 24px;
+  font-size: 12px;
+  line-height: 14px;
+}
+.text-give-day {
+  font-weight: bold;
+}
+.active-tip--success p {
+  font-size: 16px;
+  line-height: 19px;
+  color: #171826;
+  text-align: center;
+}
+.active-tip--success h5 {
+  margin-top: 150px;
+  margin-bottom: 70px;
+  font-size: 20px;
+  font-weight: bold;
+  line-height: 23px;
+}
+
+.active-tip--over {
+  background-color: #fff;
+  border-radius: 12px;
+}
+.active-tip--over h4 {
+  font-size: 20px;
+  font-weight: bold;
+  color: #171826;
+  line-height: 28px;
+  margin-top: 32px;
+  margin-bottom: 20px;
+}
+.active-tip--over p {
+  margin-top: 16px;
+  margin-bottom: 28px;
+  font-size: 14px;
+  font-weight: 500;
+  color: #5F5E64;
+  line-height: 20px;
+  text-align: center;
+}
+
+.active-tip--code p {
+  margin-top: 121px;
+  font-size: 16px;
+  font-weight: bold;
+  color: #FFFFFF;
+  line-height: 19px;
+  text-align: center;
+}
+.active-tip--code p span {
+  margin-top: 11px;
+  display: inline-block;
+  font-size: 12px;
+  font-weight: 500;
+  color: #F8F8F8;
+  line-height: 14px;
+}
+.active-tip--code .code-img img {
+  width: 100%;
+}
+.active-tip--code .code-img {
+  margin-top: 40px;
+  width: 144px;
+  height: 144px;
+  background: #FFFFFF;
+  padding: 2px;
+  box-sizing: border-box;
+  box-shadow: 0px 4px 4px 1px rgba(181, 69, 69, 0.25);
+  border-radius: 8px 8px 8px 8px;
+  overflow: hidden;
+}
+.active-tip--code .close-dialog-icon img {
+  width: 24px;
+}
+.active-tip--code .close-dialog-icon {
+  padding: 8px;
+}
+
+.close-dialog-icon img {
+  width: 16px;
+}
+.close-dialog-icon {
+  position: absolute;
+  top: 0;
+  right: 0;
+  padding: 12px;
+  cursor: pointer;
+}

+ 278 - 0
src/web/staticres/frontRouter/pc/activity/css/task-common.css

@@ -0,0 +1,278 @@
+[v-cloak] {
+  display: none!important;
+}
+.j-icon {
+  display: block;
+  width: 24px;
+  height: 24px;
+  background-repeat: no-repeat;
+  background-size: contain;
+}
+.icon-jy-coin {
+  background-image: url(/frontRouter/pc/activity/image/jianyubi@2x.png);
+}
+.icon-jy-svip {
+  background-image: url(/frontRouter/pc/activity/image/chaojidingyue@2x.png);
+}
+.icon-jy-coupon {
+  background-image: url(/common-module/active/2022.7/icon-coupon@2x.png);
+}
+.no-select {
+  user-select: none;
+}
+
+.text-gradient-red {
+  background-image: linear-gradient(90deg, #FE542F 0%, #F01313 100%);
+  -webkit-background-clip: text;
+  -webkit-text-fill-color: transparent;
+}
+
+@font-face {
+  font-family:"YouSheBiaoTiHei";
+  font-display: swap;
+  src:url('/big-member/image/new_big_index/font/YouSheBiaoTiHei-2.ttf');
+}
+
+@media screen and (max-width: 1920px) {
+  .header-banner-img {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    overflow: hidden;
+  }
+  .header-banner-img img {
+    width: unset;
+  }
+}
+
+.floating {
+  animation: floating 1.3s ease-in-out 1.3s infinite alternate;
+  transition: all 1.3s ease;
+}
+.floating.delay-100 {
+  animation-delay: 0.1s;
+}
+.floating.delay-300 {
+  animation-delay: 0.3s;
+}
+
+@keyframes floating {
+  from {
+    transform: translate(0, 0);
+  }
+  to {
+    transform: translate(0, 10px);
+  }
+}
+
+/* 任务球 start */
+.mission-list {
+  display: flex;
+  align-items: center;
+  position: absolute;
+  left: 50%;
+  bottom: -40px;
+  z-index: 2;
+  width: 1200px;
+  height: 380px;
+  transform: translateX(-50%);
+  /* background-color: pink; */
+}
+.mission-list-item {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  position: absolute;
+  left: 0;
+  top: 0;
+  transition: all 0.8s cubic-bezier(0, 0, 0.2, 1);
+  transform: scale(1);
+  z-index: 2;
+}
+.mission-list-item.exit {
+  transform: scale(0);
+}
+
+.m-list-item-bg {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: space-between;
+  padding: 30px 0;
+  width: 142px;
+  height: 138px;
+  background-image: url(/frontRouter/pc/activity/image/bubble-2@2x.png);
+  background-repeat: no-repeat;
+  background-size: contain;
+}
+.mission-list-item.complete .num,
+.mission-list-item.complete .text {
+  opacity: 1;
+}
+.mission-list-item.complete .m-list-item-bg {
+  background-image: url(/frontRouter/pc/activity/image/bubble-1@2x.png);
+}
+.m-list-item-bg .num {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  font-size: 28px;
+  font-weight: bold;
+  color: #CF1627;
+  line-height: 34px;
+  opacity: 0.6;
+}
+.num .num-add {
+  font-size: 20px;
+  font-weight: 400;
+}
+.m-list-item-bg .text {
+  font-size: 14px;
+  color: #CF1627;
+  line-height: 16px;
+  opacity: 0.6;
+}
+.m-list-item-bg .button {
+  position: relative;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  margin-top: 10px;
+  min-width: 72px;
+  padding: 4px 8px;
+  font-size: 14px;
+  color: #fff;
+  line-height: 16px;
+  background: linear-gradient(180deg, #F84B4B 0%, #E4192B 100%);
+  border-image: linear-gradient(180deg, rgba(255, 216, 216, 0), rgba(255, 216, 216, 1)) 1 round;
+  border-radius: 14px;
+  cursor: pointer;
+}
+.m-list-item-bg .button::after {
+  /* content: ''; */
+  position: absolute;
+  top: -2px;
+  bottom: -2px;
+  left: -2px;
+  right: -2px;
+  background: linear-gradient(180deg, rgba(255, 216, 216, 0), rgba(255, 216, 216, 1));
+  z-index: -1;
+  border-radius: 14px;
+}
+.m-list-item-text {
+  font-size: 18px;
+  font-weight: 700;
+  color: #CF1627;
+}
+/* 任务球 end */
+
+/* 任务进度 start */
+.progress-bar-container {
+  padding: 130px 0;
+  padding-top: 90px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+.progress-bar-label {
+  margin-right: 20px;
+  font-size: 16px;
+  line-height: 20px;
+  color: #fff;
+}
+.progress-bar {
+  position: relative;
+  width: 1000px;
+  height: 20px;
+  background: #FEC285;
+  box-shadow: inset 0px 6px 8px 1px rgba(255, 255, 255, 0.4);
+  border-radius: 20px;
+  background-color: rgba(255, 255, 255, 0.6);
+  z-index: 1;
+}
+.progress-bar-content {
+  position: relative;
+  height: 100%;
+  min-width: 22px;
+  background: linear-gradient(270deg, #FFFFFF 20%, rgba(255, 255, 255, 0) 100%);
+  border-radius: 20px;
+  z-index: 2;
+  transition: all 0.8s cubic-bezier(0.15, 0.85, 1, 1);
+}
+.blink-point {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  position: absolute;
+  top: 50%;
+  right: 0;
+  transform: translate(0,-50%);
+  width: 22px;
+  height: 22px;
+  border-radius: 50%;
+  background-color: rgba(255, 255, 255, 0.9);
+  filter: blur(8px) drop-shadow(0 0 2px rgba(255, 255, 255, 0.8)) drop-shadow(0 0 8px rgba(255, 255, 255, 0.9)) drop-shadow(0 0 16px rgba(255, 255, 255, 1));
+  z-index: 3;
+}
+.anchor {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: space-between;
+  position: absolute;
+  top: -46px;
+  left: 0;
+  color: #fff;
+  transform: translateX(-60%);
+  z-index: 4;
+  transition: all 1s cubic-bezier(0.15, 0.85, 1, 1);
+}
+.anchor.first {
+  transform: none;
+}
+.blink-point-text {
+  position: absolute;
+  right: 0;
+  top: -25px;
+  transform: translate(40%,-100%);
+}
+
+.anchor.wait .anchor-tip-text {
+  color: #fff;
+  cursor: pointer;
+}
+.anchor[disabled] .anchor-tip-text {
+  cursor: no-drop;
+  background-image: url(/frontRouter/pc/activity/image/tooltip-bottom-red-disabled@2x.png);
+  background-size: contain;
+}
+
+.anchor-text {
+  font-size: 18px;
+  font-weight: 700;
+  line-height: 22px;
+  white-space: nowrap;
+}
+.point-img {
+  width: 60px;
+  cursor: pointer;
+}
+.anchor-tip-text {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  width: 144px;
+  height: 70px;
+  font-size: 14px;
+  line-height: 18px;
+  font-weight: 700;
+  color: rgba(255, 255, 255, 0.6);
+  cursor: pointer;
+  /* background: url(/frontRouter/pc/activity/image/tooltip-bottom-red@2x.png) no-repeat; */
+  background-image: url(/frontRouter/pc/activity/image/tooltip-bottom-red-disabled@2x.png);
+  background-repeat: no-repeat;
+  background-size: contain;
+}
+/* 任务进度 end */

BIN
src/web/staticres/frontRouter/pc/activity/image/202207/activity-rule-text@2x.png


BIN
src/web/staticres/frontRouter/pc/activity/image/202207/button-large@2x.png


BIN
src/web/staticres/frontRouter/pc/activity/image/202207/button-middle@2x.png


BIN
src/web/staticres/frontRouter/pc/activity/image/202207/button-small@2x.png


BIN
src/web/staticres/frontRouter/pc/activity/image/202207/content-yure.png


BIN
src/web/staticres/frontRouter/pc/activity/image/202207/entniche-shangji@2x.png


BIN
src/web/staticres/frontRouter/pc/activity/image/202207/entniche-zhuanjia@2x.png


BIN
src/web/staticres/frontRouter/pc/activity/image/202207/header-banner.png


BIN
src/web/staticres/frontRouter/pc/activity/image/202207/more-fuli-text@2x.png


BIN
src/web/staticres/frontRouter/pc/activity/image/202207/participate-in-text@2x.png


BIN
src/web/staticres/frontRouter/pc/activity/image/202207/strategy@2x.png


BIN
src/web/staticres/frontRouter/pc/activity/image/202207/title-fuli1@2x.png


BIN
src/web/staticres/frontRouter/pc/activity/image/202207/title-fuli2@2x.png


BIN
src/web/staticres/frontRouter/pc/activity/image/202207/title-fuli3@2x.png


BIN
src/web/staticres/frontRouter/pc/activity/image/202207/title-yure@2x.png


+ 1002 - 0
src/web/staticres/frontRouter/pc/activity/js/task-202207.js

@@ -0,0 +1,1002 @@
+function Point (x, y) {
+  this.x = x
+  this.y = y
+}
+function Map (w, h) {
+  this.width = w
+  this.height = h
+}
+// 画布中生成随机不重叠的坐标
+// 坐标点以左上角为中心
+function RandomCoordinate (conf) {
+  conf = conf || {}
+  this.el = conf.el || '' // 画布选择器或者dom
+  this.pointSize = conf.pointSize || new Map(1, 1) // 坐标点半径(最大)
+  this.total = conf.total || 1 // 生成多少个随机不重叠坐标
+  this.pointCoordList = [] // 生成坐标点数组
+
+  this.init = function () {
+    if (!this.el) return console.warn('画布选择器必传')
+    // 获取画布宽高
+    this.map = this.getMapSize()
+    this.getPointCoordLimits()
+    this.create()
+  }
+
+  this.getMapSize = function () {
+    this.$el = $(this.el)
+    var w = this.$el.width()
+    var h = this.$el.height()
+    return new Map(w, h)
+  }
+
+  this.getPointCoordLimits = function () {
+    var xMax = this.map.width - this.pointSize.width
+    var yMax = this.map.height - this.pointSize.height
+    if (xMax <= 0) {
+      xMax = 1
+    }
+    if (yMax <= 0) {
+      yMax = 1
+    }
+    this.coordLimits = new Point(xMax, yMax)
+  }
+
+  // this.check
+  // 检查是否和已创建的有重叠
+  this.checkListOverlap = function (p) {
+    if (this.pointCoordList.length <= 0) return true
+    var pass = true // pass,所有都不重叠
+    for (var i = 0; i < this.pointCoordList.length; i++) {
+      var overlap = this.checkOverlap(p, this.pointCoordList[i])
+      if (overlap) {
+        pass = false
+        break
+      }
+    }
+    return pass
+  },
+  // point为矩形左上的碰撞检测:碰撞返回true
+  // 利用两圆相切,圆心距离小于2r表示两圆相交(r圆半径)。把矩形对角线看作圆的直径
+  // 如果两个矩形左上角的点间距离大于矩形对角线长度,则认为两矩形无碰撞(无重叠)
+  // 参考:https://segmentfault.com/a/1190000017463616
+  this.checkOverlap = function (nPoint, oPoint) {
+    // 两矩形左上角坐标距离(三角函数)
+    // https://www.qttc.net/171-javascript-get-two-points-distance.html
+    var dx = Math.abs(nPoint.x - oPoint.x)
+    var dy = Math.abs(nPoint.y - oPoint.y)
+    var distance = Math.sqrt(dx * dx + dy * dy)
+
+    // 矩形对角线长度
+    var w = this.pointSize.width
+    var h = this.pointSize.height
+    var diagonal = Math.sqrt(w * w + h * h)
+
+    return distance <= diagonal
+  }
+
+  // 创建一个坐标
+  this.createOne = function () {
+    var createTimes = 0
+    var createFailTimes = 0
+    var maxCreateFailTime = 200
+    var x,y
+    while (createFailTimes < maxCreateFailTime) {
+      createTimes++
+      x = Math.floor(Math.random() * this.coordLimits.x)
+      y = Math.floor(Math.random() * this.coordLimits.y)
+      var point = new Point(x, y)
+      var pass = this.checkListOverlap(point)
+      if (pass) {
+        this.pointCoordList.push(point)
+        break
+      } else {
+        createFailTimes++
+      }
+    }
+    if (createFailTimes >= maxCreateFailTime) {
+      console.log('随机生成坐标%s次失败,停止随机生成', maxCreateFailTime)
+    } else {
+      console.log('随机生成坐标次数:%s,\n随机生成坐标失败次数:%s\n获得坐标:', createTimes, createFailTimes, JSON.stringify(point))
+    }
+  }
+
+  this.create = function () {
+    for (var i = 0; i < this.total; i++) {
+      this.createOne()
+    }
+    this.pointCoordList = this.pointCoordList.sort(function (a, b) {
+      return a.x - b.x
+    })
+  }
+
+  this.init()
+}
+
+// 判断活动是否结束
+var initPageTime = new Date().getTime()
+var initActiveOverCheck = -1
+function activeOverCheck (endTime, callback) {
+  if (initPageTime >= endTime) {
+    return callback()
+  }
+  clearTimeout(initActiveOverCheck)
+  var reloadTime = endTime - new Date().getTime()
+  if (reloadTime <= (10 * 60 * 1000) ) {
+    initActiveOverCheck = setTimeout(function () {
+      callback && callback()
+    }, reloadTime)
+  }
+}
+
+// toast上限提示
+function toastFn (text, duration) {
+  if (!duration) {
+    duration = 1000
+  }
+  var _html = ""
+  _html+='<div class="custom-toast"><div class="mask" style="background-color: transparent;"></div><div class="toast-container">'
+  _html+='<span>' + text + '</span></div></div>'
+  $('body').append(_html)
+  setTimeout(function(){
+    $(".custom-toast").fadeOut().remove();
+  },duration)
+}
+
+// 展示弹窗
+function showDialogOfType (type) {
+  $('#active-tip-modal').attr('data-modal-type', 'success').modal('show')
+  $('#active-tip-modal').attr('data-modal-type', 'over').modal('show')
+  $('#active-tip-modal').attr('data-modal-type', 'code').modal('show')
+  var modal = $('#active-tip-modal')
+  modal.attr('data-modal-type', type).modal('show')
+  if (type === 'over') {
+    modal.off('click')
+  } else {
+    modal.off('click').on('click', function () {
+      modal.modal('hide')
+    })
+  }
+}
+
+// 固定事件
+$(function () {
+  // 弹窗按钮事件
+  $('#dialog-button--over').on('click', function () {
+    window.open('/swordfish/frontPage/share/sess/index')
+  })
+  $('#dialog-button--success').on('click', function () {})
+})
+
+var task = new Vue({
+  el: '#main-app',
+  delimiters: ['${', '}'],
+  data: {
+    conf: {
+      before: 0, // 单位: s
+      clock: '10:00:00',
+      end: 0, // 单位: s
+      now: 0, // 单位: s
+      start: 0 // 单位: s
+    },
+    activeState: '',
+    lastTimestamp: 0, // 单位: ms
+    timeDuration: {
+      yure: '', // 预热活动时间7.25-7.31
+      active: '' // 活动时间8.1-8.14
+    },
+    yureConf: {
+      total: 0,
+      got: false
+    },
+    yureInfo: {
+      timerId: null,
+      tipText: '',
+      buttonText: '点击免费领',
+      buttonDisabled: false
+    },
+    couponList: [],
+    progress: {
+      min: 0,
+      max: 1500,
+      current: 0, // 当前剑鱼币
+      pointImgMap: {
+        unreceived: '/frontRouter/pc/activity/image/unreceived@2x.png',
+        received: '/frontRouter/pc/activity/image/received@2x.png',
+        wait: '/frontRouter/pc/activity/image/received@2x.png'
+      },
+      anchorList: [
+        {
+          id: '',
+          className: 'first',
+          rate: 0, // 进度,单位%,最大为100
+          pointImg: '', // ''/unreceived/received
+          anchorText: '0剑鱼币'
+        },
+        {
+          id: '800',
+          className: 'unreceived',
+          rate: 80,
+          pointImg: 'unreceived',
+          anchorText: '800剑鱼币',
+          tipText: '1个月超级订阅'
+        },
+        {
+          id: '1500',
+          className: 'unreceived',
+          rate: 100,
+          pointImg: 'unreceived',
+          anchorText: '1500剑鱼币',
+          tipText: '1个月超级订阅'
+        }
+      ],
+    },
+    // 任务球
+    missionsList: [
+      {
+        id: 'buyvip',
+        className: '',
+        x: 190,
+        y: 120,
+        num: 800,
+        unit: '剑鱼币',
+        complete: false,
+        hide: true,
+        name: '购买超级订阅' // 任务描述
+      },
+      {
+        id: 'invite',
+        className: 'delay-100',
+        x: 380,
+        y: 0,
+        num: 500,
+        unit: '剑鱼币',
+        complete: false,
+        hide: true,
+        name: '邀请领好礼'
+      },
+      {
+        id: 'share',
+        className: 'delay-300',
+        x: 900,
+        y: 80,
+        num: 200,
+        unit: '剑鱼币',
+        complete: false,
+        hide: true,
+        name: '分享活动'
+      }
+    ],
+    copyLinkText: location.href,
+    rewardList: [],
+    dialog: {
+      myReward: false
+    },
+    rulesList: [
+      {
+        text: '活动时间:预热期:7.25-7.31 、活动期:8.1-8.14。'
+      },
+      {
+        text: '预热福利:预热期内用户每天10点开始领取,每天限量500份,每天0点数量更新,每人仅限领取一次,数量有限,先到先得。'
+      },
+      {
+        text: '福利一:官方补贴限时抢 购买超级订阅立减:活动期间内新购、续费、升级用户均可参加,通过活动页领取优惠券后购买超级订阅可享受满减,不同额度优惠券一人仅限领取1张,优惠券仅限领取后活动期内使用,过期无效。'
+      },
+      {
+        text: '福利二:做任务 得2个月超级订阅:活动期内,用户分别完成各任务即可获得相对应的剑鱼币,达到1000剑鱼币领1个月超级订阅,达到1500剑鱼币领1个月超级订阅,领取后在原有购买时间上延长所领取奖励的时长,在订单支付期间,完成【购买超级订阅】可获得800剑鱼币,用户新购、续费、升级皆可获得剑鱼币奖励,完成【邀请领好礼】可获得500剑鱼币,完成【分享活动】可获得200剑鱼币;完成购买超级订阅、邀请领好礼、分享活动三个任务且活动页剑鱼币累计达到1000剑鱼币或1500剑鱼币即可领取超级订阅,累计可领2个月,通过其他形式获取的剑鱼币将不作为领取奖励的依据,领取后在【我的奖励】中查看。'
+      },
+      {
+        text: '福利三:大会员最高立减7999元 送6个月使用时长:活动期内商机版2.0最高立减3199元,购买赠送6个月使用时长,专家版2.0最高立减7999元,购买赠送6个月使用时长,点击【了解更多】可详细了解大会员服务内容,详情请致电咨询:400-108-6670,线下购买享优惠。'
+      },
+      {
+        text: '本次活动不支持作弊行为,涉嫌违法、违规参与活动的用户,剑鱼标讯将有权取消您的活动参与资格,并回收已获得的相关奖励,由于不可抗力因素等情况导致活动异常,剑鱼标讯将有权采取调整等措施。'
+      },
+      {
+        text: '法律许可范围内本次活动解释权归北京剑鱼信息技术有限公司所有。'
+      }
+    ]
+  },
+  computed: {
+    rate: function () {
+      var calcRate = (this.progress.current / this.progress.max) * 100
+      if (calcRate > 100) {
+        calcRate = 100
+      }
+      if (calcRate < 0) {
+        calcRate = 0
+      }
+      return calcRate
+    },
+    blinkTextShow: function () {
+      var anchorList = this.progress.anchorList
+      var rate = this.rate
+      var exist = false
+      for (var i = 0; i < anchorList.length; i++) {
+        if (rate === anchorList[i].rate) {
+          exist = true
+          break
+        }
+      }
+      return !exist
+    },
+    progressAnchorList: function () {
+      return this.progress.anchorList
+    },
+    lastTimeText: function () {
+      if (this.lastTimestamp > 0) {
+        var lastTimeConf = this.calcLastTimeDiff(this.lastTimestamp)
+        var days = lastTimeConf.days
+        var hours = lastTimeConf.hours
+        var minutes = lastTimeConf.minutes
+        var seconds = lastTimeConf.seconds
+        var hms = [this.add0(hours), this.add0(minutes), this.add0(seconds)].join(':')
+        if (days > 0) {
+          return days + '天 ' + hms
+        } else {
+          return hms
+        }
+        // return days + '天 ' + hms
+      } else {
+        return ''
+      }
+    },
+    onKeyReceiveShow: function () {
+      var arr = []
+      this.couponList.forEach(function (item) {
+        if (item.IsReceive === false && item.IsUser) {
+          arr.push(item)
+        }
+      })
+      return arr.length !== this.couponList.length
+    },
+    calcYuReTopText: function () {
+      if (this.activeState === 'yureing') {
+        return '进行中'
+      } else if (this.activeState === 'waiting') {
+        return '未开始'
+      } else {
+        return '已结束'
+      }
+    },
+    yureSectionShow: function () {
+      return this.activeState === 'waiting' || this.activeState === 'yureing'
+    },
+    yureButtonShow: function () {
+      var lastTimeConf = this.calcLastTimeDiff(this.lastTimestamp)
+      var days = lastTimeConf.days
+      if (this.yureInfo.buttonText) {
+        return !(days < 1 && this.yureConf.total <= 0)
+      } else {
+        return false
+      }
+    }
+  },
+  created: function () {
+    this.ajaxActiveStatus()
+    this.ajaxProgress()
+    this.ajaxList()
+  },
+  mounted: function () {
+    // this.calcPointList()
+    this.stickyTopEvents()
+  },
+  methods: {
+    add0: function (t) {
+      return t < 10 ? ('0' + t) : t
+    },
+    ajaxActiveStatus: function () {
+      var _this = this
+      $.ajax({
+        url: '/jyActivity/membershipDay/period',
+        type: 'post',
+        success: function (res) {
+          if (res.data) {
+            for (var key in _this.conf) {
+              _this.conf[key] = res.data[key]
+            }
+
+            if (Math.abs(initPageTime - res.data.now * 1000) > 5000) {
+              initPageTime = res.data.now
+            }
+            activeOverCheck(res.data.end * 1000, function () {
+              showDialogOfType('over')
+            })
+            _this.initPageState()
+          }
+        },
+        complete: function () {
+          _this.getYuReCouponCount()
+          _this.getFuLi2CouponList()
+        }
+      })
+    },
+    initPageState: function () {
+      var state = this.checkActiveState()
+      var yureTextDOM = $('.timeline-item.yure .t-r-b-r')
+      if (state === 'yureing') {
+        this.startTopTimer()
+        yureTextDOM.text('进行中')
+      } else {
+        yureTextDOM.text('已结束')
+        if (state === 'activating') {
+          // 活动进行中
+        } else {
+
+        }
+      }
+    },
+    // 检查状态
+    checkActiveState: function (now) {
+      if (!now) {
+        now = Date.now()
+      }
+      var before = this.conf.before * 1000 // 预热开始
+      var start = this.conf.start * 1000 // 活动开始
+      var end = this.conf.end * 1000 // 活动结束
+      var stateArr = ['waiting', 'yureing', 'activating', 'ended']
+      var state = 'waiting'
+      if (now < before) {
+        state = stateArr[0] // 预热未开始
+      } else if (before <= now && now < start) {
+        state = stateArr[1] // 预热中
+      } else if (start <= now && now < end) {
+        state = stateArr[2] // 活动进行中
+      } else {
+        state = stateArr[3] // 活动已结束
+      }
+      this.activeState = state
+
+      // 计算时间间隔
+      var beforeStr = moment(before).format('M.DD')
+      var beforeStrEnd = moment(start - 1000).format('M.DD')
+      var startStr = moment(start).format('M.DD')
+      var endStr = moment(end - 1000).format('M.DD')
+
+      this.timeDuration.yure = [beforeStr, beforeStrEnd].join('-')
+      this.timeDuration.active = [startStr, endStr].join('-')
+
+      return state
+    },
+    // type=yure判断预热是否开始
+    // type=active 判断活动是否开始
+    activeNotStartToast: function (type) {
+      var state = this.checkActiveState()
+      type = type || 'active'
+      if (state === 'ended') {
+        toastFn('活动已结束')
+      } else if (state === 'waiting') {
+        toastFn('活动尚未开始,敬请期待')
+      } else {
+        if (type === 'yure') {
+          if (state === 'activating') {
+            // 预热已结束
+            toastFn('预热已结束')
+          }
+        } else {
+          if (state === 'yureing') {
+            toastFn('活动尚未开始,敬请期待')
+          }
+        }
+      }
+    },
+    startTopTimer: function () {
+      var _this = this
+      var start = this.conf.start * 1000
+      var timerId = setInterval(function () {
+        var current = Date.now()
+        if (_this.lastTimestamp < 0) {
+          clearInterval(timerId)
+        }
+        _this.lastTimestamp = start - current
+      }, 1000)
+    },
+    calcYuReText: function () {
+      var _this = this
+      var buttonText = ''
+      var tipText = ''
+      var buttonDisabled = true
+      if (this.yureInfo.timerId) {
+        clearInterval(this.yureInfo.timerId)
+      }
+      if (this.activeState === 'yureing') {
+        // 当天时间
+        var todayString = new Date().pattern('yyyy/MM/dd')
+        // 当领券开始时间
+        var yureCouponStartTime = [todayString, this.conf.clock].join(' ')
+        var yureCouponStartStamp = +new Date(yureCouponStartTime)
+        // 计算倒计时
+        var diff = yureCouponStartStamp - Date.now()
+        if (diff > 0) {
+          // 预热当天未开始抢券
+          buttonDisabled = true
+          // 计算小时
+          if (this.conf.clock) {
+            var clockArr = this.conf.clock.split(':')
+            buttonText = '今日'+ clockArr[0] +'点开抢'
+          } else {
+            buttonText = '今日10点开抢'
+          }
+          // 创建定时器刷新倒计时
+          this.yureInfo.timerId = setInterval(function () {
+            var d = yureCouponStartStamp - Date.now()
+            var obj = _this.calcLastTimeDiff(d)
+            if (d <= 0) {
+              clearInterval(_this.yureInfo.timerId)
+              _this.calcYuReText()
+            } else {
+              // 计算倒计时
+              tipText = [_this.add0(obj.hours), _this.add0(obj.minutes), _this.add0(obj.seconds)].join(':')
+              _this.yureInfo.tipText = tipText
+            }
+          }, 1000)
+        } else {
+          if (this.yureConf.got) {
+            // 已领取过
+            buttonDisabled = false
+            buttonText = '去查看'
+            tipText = '已领取成功'
+          } else {
+            buttonDisabled = this.yureConf.total <= 0
+            // 券是否有剩余
+            if (this.yureConf.total > 0) {
+              buttonText = '点击免费领'
+              tipText = '今日还剩<span class="num">' + this.yureConf.total + '</span>份'
+            } else {
+              // 今日券领完了
+              buttonText = '今天已抢完'
+              tipText = '今天已经抢完啦~明天再来吧'
+            }
+          }
+        }
+      } else {
+        // 预热未开始或者预热结束
+      }
+
+      this.yureInfo.buttonDisabled = buttonDisabled
+      this.yureInfo.buttonText = buttonText
+      this.yureInfo.tipText = tipText
+    },
+    calcLastTimeDiff: function (timestamp) {
+      var diff = moment.duration(Math.abs(timestamp))
+      var days = diff.days()
+      var hours = diff.hours()
+      var minutes = diff.minutes()
+      var seconds = diff.seconds()
+      return {
+        days: days,
+        hours: hours,
+        minutes: minutes,
+        seconds: seconds
+      }
+    },
+    // 预热优惠券数量查询
+    getYuReCouponCount: function () {
+      var _this = this
+      $.ajax({
+        url: '/jyActivity/membershipDay/getDailyBoonDetail',
+        type: 'post',
+        success: function (res) {
+          if (res.data) {
+            _this.yureConf.got = res.data.got || false
+            _this.yureConf.total = res.data.total || 0
+            _this.calcYuReText()
+          }
+        }
+      })
+    },
+    receiveYuReCoupon: function () {
+      if (this.yureInfo.buttonDisabled) {
+        toastFn('活动尚未开始,敬请期待')
+      } else if (this.yureInfo.buttonText === '去查看') {
+        // 领过了
+        this.toOrderPage()
+      } else {
+        // 没领过
+        this.receiveYuReCouponAjax()
+      }
+    },
+    // 领取预热优惠券
+    receiveYuReCouponAjax: function () {
+      var _this = this
+      $.ajax({
+        url: '/jyActivity/membershipDay/getDailyBoonSVip',
+        type: 'post',
+        success: function (res) {
+          if (res.data) {
+            toastFn('领取成功')
+            _this.getYuReCouponCount()
+            // 刷新我的奖励列表
+            _this.ajaxList()
+          }
+        }
+      })
+    },
+    receiveActiveButtonText: function (item) {
+      if (item.IsReceive) {
+        return '立即领取'
+      } else {
+        if (item.IsUser) {
+          return '去使用'
+        } else {
+          return '已使用'
+        }
+      }
+    },
+    receiveActiveCoupon: function (coupons) {
+      if (this.activeState !== 'activating') {
+        return this.activeNotStartToast()
+      }
+      if (coupons.length === 0) return
+      if (coupons.length === 1) {
+        var item = coupons[0]
+        if (!item.IsReceive && item.IsUser) {
+          return this.toBuyVip()
+        }
+      }
+      var idArr = []
+      coupons.forEach(function (item) {
+        if (item.IsReceive) {
+          idArr.push(item.LotteryIdStr)
+        }
+      })
+      this.receiveActiveCouponAjax(idArr)
+    },
+    // 领取活动优惠券
+    receiveActiveCouponAjax: function (ids) {
+      if (ids.length === 0) return
+      var _this = this
+      $.ajax({
+        url: '/jyActivity/membershipDay/getLottery',
+        type: 'post',
+        contentType: 'application/json',
+        data: JSON.stringify({
+          lotteryIds: ids.join(',')
+        }),
+        success: function (res) {
+          if (res.data) {
+            _this.couponList.forEach(function (item) {
+              if (ids.indexOf(item.LotteryIdStr) !== -1) {
+                item.IsReceive = false
+                item.IsUser = true
+              }
+            })
+            toastFn('领取成功')
+            // 刷新我的奖励列表
+            _this.ajaxList()
+          }
+        }
+      })
+    },
+    addTipText: function (list) {
+      var prefix = '超级订阅'
+      var priceArr = [
+        {
+          price: 38,
+          text: '1个月+1个省'
+        },
+        {
+          price: 99,
+          text: '1个季+1个省'
+        },
+        {
+          price: 380,
+          text: '1年+1个省'
+        },
+        {
+          price: 599,
+          text: '1个月+全国'
+        },
+      ]
+      var arr = list.sort(function (a, b) {
+        return a.Reduce - b.Reduce
+      })
+      list.forEach(function (item) {
+        var reduce = item.Reduce
+        var full = item.Full
+        for (var i = 0; i < priceArr.length; i++) {
+          if (priceArr[i].price - full >= 0) {
+            var pay = priceArr[i].price - reduce
+            item.tipText = prefix + priceArr[i].text + ':券后' + pay + '元'
+            break
+          }
+        }
+      })
+      return arr
+    },
+    // 获取福利2优惠券列表
+    getFuLi2CouponList: function () {
+      var _this = this
+      $.ajax({
+        url: '/jyActivity/membershipDay/lotteryList',
+        type: 'post',
+        success: function (res) {
+          if (res.data) {
+            _this.couponList = _this.addTipText(res.data) || []
+            // 刷新我的奖励列表
+            _this.ajaxList()
+          }
+        }
+      })
+    },
+    calcPointList: function () {
+      var dom = this.$refs.missions
+      window.points = new RandomCoordinate({
+        el: dom,
+        total: this.missionsList.length,
+        pointSize: new Map(142, 160)
+      })
+      var pointList = points.pointCoordList
+      for (var i = 0; i < this.missionsList.length; i++) {
+        this.missionsList[i].x = pointList[i].x
+        this.missionsList[i].y = pointList[i].y
+      }
+    },
+    leaveCanvas: function (item) {
+      var dom = $('.mission-list-item.' + item.id)
+      dom.removeClass('floating')
+      var baseX = 84
+      var baseY = 34
+      // 终点坐标
+      var current = {
+        x: baseX + 1000 * this.rate / 100,
+        y: baseY + $('.mission-list').height() - $('.blink-point').height() / 2
+      }
+      item.x = current.x
+      item.y = current.y
+      this.$nextTick(function () {
+        dom.addClass('exit')
+      })
+    },
+    onClickListItem: function (item) {
+      if (item.icon === 'jy-svip') {
+        this.toOrderPage()
+      } else if (item.icon === 'jy-coin') {
+        window.open('/swordfish/integral/index/detail')
+      } else {
+        // 跳转我的奖券
+        window.open('/swordfish/coupon/')
+        // this.toBuyVip()
+      }
+    },
+    onClickReceive: function (type, item) {
+      if (this.activeState !== 'activating') return toastFn('活动尚未开始,敬请期待')
+      if (item.className === 'received') return
+      var status = false
+      if (type === 'schedule') {
+        if (item.className === 'wait') {
+          status = true
+        } else {
+          var text = '尚未达到领取条件,无法领取'
+          switch (item.id) {
+            // 800
+            case this.progressAnchorList[1].id: {
+              text = '尚未达到'+ this.progressAnchorList[1].id +'剑鱼币,无法领取'
+              break
+            }
+            // 1500
+            case this.progressAnchorList[2].id: {
+              text = '尚未达到'+ this.progressAnchorList[2].id +'剑鱼币,无法领取'
+              break
+            }
+          }
+          return toastFn(text, 1500)
+        }
+      } else if (type === 'mission' && item.complete) {
+        status = true
+      }
+      if (!status) {
+        var _this = this
+        switch (item.id) {
+          case 'buyvip': {
+            this.toBuyVip()
+            break
+          }
+          case 'invite': {
+            window.open('/swordfish/frontPage/share/sess/index')
+            break
+          }
+          case 'share': {
+            // 分享
+            _this.scrollTo('.copy-share-container')
+            break
+          }
+        }
+        return
+      }
+      var _this = this
+      if (type === 'mission') {
+        this.leaveCanvas(item)
+      }
+      this.ajaxReceive({ type: type, value: item.id }, function (result, msg) {
+        if (result) {
+          switch (item.id) {
+            case 'buyvip':
+            case 'invite':
+            case 'share': {
+              toastFn('已成功领取' + item.num + '剑鱼币', 1500)
+              break
+            }
+            case '800': {
+              $('.active-tip--success .text-give-day').text('7天')
+              showDialogOfType('success')
+              break
+            }
+            case '1500': {
+              $('.active-tip--success .text-give-day').text('1个月')
+              showDialogOfType('success')
+              break
+            }
+          }
+          _this.ajaxActiveStatus()
+          _this.ajaxProgress()
+          _this.ajaxList()
+        } else {
+          toastFn(msg, 1500)
+        }
+      })
+    },
+    ajaxReceive: function (data, callback) {
+      var _this = this
+      $.ajax({
+        url: '/jyActivity/membershipDay/receive',
+        type: 'post',
+        contentType: 'application/json',
+        data: JSON.stringify(data),
+        success: function (res) {
+          callback(res.data, res.error_msg)
+          // 刷新我的奖励列表
+          _this.ajaxList()
+        }
+      })
+    },
+    ajaxProgress: function () {
+      var _this = this
+      $.ajax({
+        url: '/jyActivity/membershipDay/schedule',
+        type: 'post',
+        success: function (res) {
+          if (res.error_code === 0 && res.data) {
+            _this.progress.current = res.data.nowNum
+
+            _this.missionsList[0].complete = res.data.missions.buyvip !== 0
+            _this.missionsList[1].complete = res.data.missions.invite !== 0
+            _this.missionsList[2].complete = res.data.missions.share !== 0
+
+            _this.missionsList[0].hide = res.data.missions.buyvip === -1
+            _this.missionsList[1].hide = res.data.missions.invite === -1
+            _this.missionsList[2].hide = res.data.missions.share === -1
+
+            var anchorStatus = {
+              1: 'wait',
+              0: 'unreceived',
+              '-1': 'received',
+            }
+            var imgStatus = {
+              1: 'unreceived',
+              0: 'unreceived',
+              '-1': 'received',
+            }
+
+            _this.progress.anchorList[1].className = anchorStatus[res.data.schedule['800']]
+            _this.progress.anchorList[2].className = anchorStatus[res.data.schedule['1500']]
+
+            _this.progress.anchorList[1].pointImg = imgStatus[res.data.schedule['800']]
+            _this.progress.anchorList[2].pointImg = imgStatus[res.data.schedule['1500']]
+          }
+        }
+      })
+    },
+    ajaxList: function () {
+      var _this = this
+      $.ajax({
+        url: '/jyActivity/myAward/awardlist',
+        type: 'post',
+        contentType: 'application/json',
+        data: JSON.stringify({
+          code: 'membershipDay',
+          pageSize: 10,
+          pageNum: 0
+        }),
+        success: function (res) {
+          if (res.error_code === 0 && res.data) {
+            if (res.data.list && typeof res.data.list.map === 'function') {
+              _this.rewardList = res.data.list.map(function (v) {
+                var icon = ''
+                if (v.award.indexOf('剑鱼币') > -1) {
+                  icon = 'jy-coin'
+                } else if (v.award.indexOf('订阅') > -1) {
+                  icon = 'jy-svip'
+                } else {
+                  icon = 'jy-coupon'
+                }
+                return {
+                  id: v._id,
+                  icon: icon,
+                  rewardText: v.award,
+                  receiveTime: new Date(v.date * 1000).pattern('yyyy-MM-dd HH:mm:ss'),
+                  receiveFrom: v.getway
+                }
+              })
+            }
+          }
+        }
+      })
+    },
+    receiveFuli3: function () {
+      if (this.activeState !== 'activating') {
+        return this.activeNotStartToast()
+      }
+      vm.isNeedSubmit('super_membership_day',function(){
+        vm.showSuccess = true
+      })
+    },
+    doCopy: function () {
+      if (this.activeState === 'activating') {
+        var _this = this
+        $.ajax({
+          url: '/jyActivity/membershipDay/doShare',
+          type: 'post',
+          success: function (res) {
+            if (res.data) {
+              toastFn('复制成功')
+              _this.ajaxProgress()
+            }
+          }
+        })
+      } else {
+        // toastFn('活动尚未开始,敬请期待')
+        this.activeNotStartToast()
+      }
+      this.copyText('快来和我一起参与吧!剑鱼超级会员节,百万补贴限量抢,快速获取商机信息》\n' + this.copyLinkText)
+    },
+    copyText: function (text) {
+      const input = document.createElement('textarea') // js创建一个input输入框
+      input.value = text // 将需要复制的文本赋值到创建的input输入框中
+      document.body.appendChild(input) // 将输入框暂时创建到实例里面
+      input.select() // 选中输入框中的内容
+      document.execCommand('copy') // 执行复制操作
+      document.body.removeChild(input) // 最后删除实例中临时创建的input输入框,完成复制操作
+    },
+    scrollTo: function (className) {
+      setTimeout(function () {
+        var offsetTop = $(className)[0].offsetTop - 64 * 2
+        $(window).scrollTop(offsetTop)
+      }, 100)
+    },
+    stickyTopEvents: function () {
+      var _this = this
+      var fixedTop = $('.fixed-top.top-timeline')
+      var showHide = function () {
+        var scrollTop = $(window).scrollTop()
+        if (scrollTop > 600) {
+          fixedTop.show()
+        } else {
+          fixedTop.hide()
+        }
+      }
+      showHide()
+      $(window).on('scroll', function () {
+        showHide()
+      })
+      fixedTop.on('click', '.timeline-item', function (e) {
+        $(e.currentTarget).addClass('active').siblings().removeClass('active')
+        var className = $(e.currentTarget).attr('data-s-class')
+        _this.scrollTo('.' + className)
+      })
+    },
+    toOrderPage: function () {
+      window.open('/front/swordfish/toMyOrder')
+    },
+    toMemberPage: function () {
+      window.open('/big/page/index')
+    },
+    toBuyVip: function () {
+      if (window.vipStatus > 0) {
+        window.open('/swordfish/page_big_pc/free/svip/buy?type=upgrade')
+      } else {
+        // 去购买
+        window.open('/swordfish/page_big_pc/free/svip/buy?type=buy')
+      }
+    }
+  }
+})

+ 1 - 3
src/web/staticres/frontRouter/pc/coupon/js/coupon-item-template.js

@@ -14,8 +14,6 @@ var couponItemString = `
                 </span>
                 <span class="info-condition">满{{ full }}可用</span>
             </div>
-            <div class="info-content c-i-h-p-voucher" key="content" v-else-if="attribute.indexOf('实物') != -1">实物券</div>
-            <div class="info-content c-i-h-others" key="content" v-else>优惠券</div>
         </div>
         <div class="c-i-h-date">
             <span class="c-i-h-date-l">{{ useDate }}</span>
@@ -27,7 +25,7 @@ var couponItemString = `
             <span class="ch-label">适用产品:</span>
             <span class="ch-text ellipsis">{{ productionsListStr }}</span>
             <el-popover
-                v-if="productionsListStr.length >= 15"
+                v-if="productionsListStr && productionsListStr.length >= 15"
                 class="ch-icon"
                 :placement="popoverConf.placement"
                 :width="popoverConf.width"

+ 38 - 34
src/web/staticres/js/monitor/new_monitor.js

@@ -1,35 +1,39 @@
-MITO.init({
-  async beforeDataReport(event){
-    var filterList = [
-      window.location.pathname,
-      "huiju",
-      "thirdwx.qlogo.cn",
-      "baidu",
-      "cnzz",
-      "sobot"
-    ]
-    var msg = event.data.message;
-    for (k of filterList) {
-      if (msg.indexOf(k)>=0){
-        console.log(msg)
-        return false;
+try {
+  MITO.init({
+    async beforeDataReport(event){
+      var filterList = [
+        window.location.pathname,
+        "huiju",
+        "thirdwx.qlogo.cn",
+        "baidu",
+        "cnzz",
+        "sobot"
+      ]
+      var msg = event.data.message;
+      for (k of filterList) {
+        if (msg.indexOf(k)>=0){
+          console.log(msg)
+          return false;
+        }
       }
-    }
-		return event
-   },
-    // 服务器地址  线上改成线上地址
-    dsn: '/monitor/report',
-    // 项目对应apikey
-    apikey: 'jy-front',
-    debug: false,
-    maxDuplicateCount: 1,
-    silentXhr: true,
-    silentFetch: true,
-    silentConsole: true,
-    silentDom: true,
-    silentHistory: true,
-    silentUnhandledrejection: false,
-    silentHashchange: true,
-    silentVue: false,
-    maxBreadcrumbs:1,
-});
+      return event
+     },
+      // 服务器地址  线上改成线上地址
+      dsn: '/monitor/report',
+      // 项目对应apikey
+      apikey: 'jy-front',
+      debug: false,
+      maxDuplicateCount: 1,
+      silentXhr: true,
+      silentFetch: true,
+      silentConsole: true,
+      silentDom: true,
+      silentHistory: true,
+      silentUnhandledrejection: false,
+      silentHashchange: true,
+      silentVue: false,
+      maxBreadcrumbs:1,
+  });
+} catch (error) {
+  console.log(error)
+}

+ 3 - 0
src/web/staticres/public-pc/js/article-content.js

@@ -1217,6 +1217,9 @@ $(function(){
   // $(".com-original").attr("dataHref",originalhref);
   // 点击阅读原文 用户留资
   $(".com-original").on('click',function() {
+    if (entService) {
+      return window.open(originalhref)
+    }
     if (!loginflag) {
       openLoginDig()
       return

+ 1 - 1
src/web/staticres/public-pc/js/header-nav.js

@@ -80,7 +80,7 @@ function trySelectNav (name) {
     }
 
     // 导航栏是否固定
-    var noFixedArr = ['/article/indexcontent','/article/content', '/article/mailprivate']
+    var noFixedArr = ['/article/indexcontent','/article/content', '/article/mailprivate', '/article/entservice']
     var hasPage = noFixedArr.some(function (v) {
       return $href.indexOf(v) !== -1
     })

+ 369 - 0
src/web/templates/frontRouter/pc/activity/sess/task-202207.html

@@ -0,0 +1,369 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>剑鱼标讯,全行业招标信息智能推送领导者</title>
+    <meta content="IE=edge,Chrome=1" http-equiv="X-UA-Compatible"/>
+    <meta content="招标订阅,招标项目,中标项目,招标信息,剑鱼标讯" name="Keywords"/>
+    <meta content="使用剑鱼标讯,可以精准匹配招标信息,只需要微信关注剑鱼标讯公众号,然后自行设定所关注的招标关键词和地区,满足订阅需求的招标信息就会在两个小时内自动推送。" name="Description"/>
+    <meta content="webkit" name="renderer">
+    <meta content="telephone=no" name="format-detection"/>
+    <meta content="" theme="dark" name="enable-header">
+    {{include "/common/pnc.html"}}
+    <link href='{{Msg "seo" "cdn"}}/css/reset.css?v={{Msg "seo" "version"}}' rel="stylesheet" type="text/css"/>
+    <link href='{{Msg "seo" "cdn"}}/pccss/reset_pc.css' rel="stylesheet" type="text/css"/>
+    <link href='{{Msg "seo" "cdn"}}/css/pc.css?v={{Msg "seo" "version"}}' rel="stylesheet"/>
+    <link href='{{Msg "seo" "cdn"}}/pccss/public-nav-1200.css?v={{Msg "seo" "version"}}' rel="stylesheet" type="text/css"/>
+    <link href="//cdn-common.jianyu360.com/cdn/lib/element-ui/2.15.7/lib/theme-chalk/index.css" rel="stylesheet" />
+    <link href='{{Msg "seo" "cdn"}}/css/collect-user-info.css?v={{Msg "seo" "version"}}' rel="stylesheet">
+    <link href='{{Msg "seo" "cdn"}}/frontRouter/pc/activity/css/task-common.css?v={{Msg "seo" "version"}}' rel="stylesheet" />
+    <link href='{{Msg "seo" "cdn"}}/frontRouter/pc/activity/css/task-202207.css?v={{Msg "seo" "version"}}' rel="stylesheet" />
+    <style>
+        .page--web--index .page-container {
+            min-height: calc(100vh - 364px);
+            box-sizing: border-box;
+        }
+        .custom-toast {
+          /* display: none; */
+        }
+        .custom-toast .toast-container{
+          /* display: none; */
+          position: fixed;
+          top: 50%;
+          left: 50%;
+          width: auto;
+          padding: 16px 32px;
+          font-size: 16px;
+          background: rgba(0, 0, 0, 0.65);
+          border-radius: 8px;
+          color: #fff;
+          transform: translateX(-50%) translateY(-50%);
+          z-index: 99;
+        }
+    </style>
+</head>
+<body class="page--web--index">
+{{include "/common/pchead.html"}}
+<div class="w-box page-container" id="main-app" v-cloak>
+    <div class="header-banner">
+        <div class="header-banner-img">
+            <img class="" src="{{Msg "seo" "cdn"}}/frontRouter/pc/activity/image/202207/header-banner.png" alt="">
+        </div>
+        <div class="header-strategy">
+            <div class="w">
+                <img src="{{Msg "seo" "cdn"}}/frontRouter/pc/activity/image/202207/strategy@2x.png" alt="">
+            </div>
+        </div>
+    </div>
+    <div class="content-container">
+        <!-- 预热 -->
+        <div class="w section no-select section-yure" v-show="yureSectionShow">
+            <div class="section-header">
+                <div class="section-header-button">
+                    <img src="{{Msg "seo" "cdn"}}/frontRouter/pc/activity/image/202207/title-yure@2x.png" alt="">
+                </div>
+            </div>
+            <div class="section-content">
+                <img src="{{Msg "seo" "cdn"}}/frontRouter/pc/activity/image/202207/content-yure.png" alt="">
+                <div class="content-info">
+                    <div class="c-info-text" v-html="yureInfo.tipText"></div>
+                    <button
+                        class="c-info-button section-button button-large"
+                        @click="receiveYuReCoupon"
+                        :disabled="yureInfo.buttonDisabled"
+                        v-show="yureButtonShow"
+                        v-text="yureInfo.buttonText"></button>
+                </div>
+            </div>
+        </div>
+        <!-- 更多活动即将开启 -->
+        <div class="w section no-select section-more-activities" v-show="yureSectionShow">
+            <div class="section-header">
+                <div class="header-text">
+                    <img src="{{Msg "seo" "cdn"}}/frontRouter/pc/activity/image/202207/more-fuli-text@2x.png" alt="">
+                </div>
+            </div>
+        </div>
+        <!-- 福利一 -->
+        <div class="w section no-select section-fuli1">
+            <div class="section-header">
+                <div class="section-header-button">
+                    <img src="{{Msg "seo" "cdn"}}/frontRouter/pc/activity/image/202207/title-fuli1@2x.png" alt="">
+                </div>
+            </div>
+            <div class="section-content coupon-list">
+                <div
+                    v-for="item in couponList"
+                    :key="item.id"
+                    class="coupon-item">
+                    <div class="coupon-title">满<span v-text="item.Full"></span>可用</div>
+                    <div class="coupon-value"><span class="num" v-text="item.Reduce">50</span>元</div>
+                    <button class="section-button button-small" @click="receiveActiveCoupon([item])" v-text="receiveActiveButtonText(item)"></button>
+                    <div class="coupon-text" v-text="item.tipText"></div>
+                </div>
+            </div>
+            <div class="section-footer">
+                <button class="section-button button-middle" v-show="onKeyReceiveShow" :disabled="couponList.length === 0" @click="receiveActiveCoupon(couponList)">一键领取</button>
+            </div>
+        </div>
+        <!-- 福利二 -->
+        <div class="w section no-select section-fuli2">
+            <div class="section-header">
+                <div class="section-header-button">
+                    <img src="{{Msg "seo" "cdn"}}/frontRouter/pc/activity/image/202207/title-fuli2@2x.png" alt="">
+                </div>
+            </div>
+            <div class="section-content mission-list" ref="missions">
+                <img class="mission-list-img" src="{{Msg "seo" "cdn"}}/common-module/active/2022.7/gift-box.png" alt="">
+                <div
+                    class="mission-list-item floating"
+                    :id="'bubble-' + item.id"
+                    :class="{ complete: item.complete, [item.id]: true, [item.className]: true }"
+                    v-for="item in missionsList"
+                    v-show="!item.hide"
+                    :style="{ left: item.x + 'px', top: item.y + 'px' }"
+                    :key="item.id">
+                    <div class="m-list-item-bg" :id="'bubble-button--' + item.id" @click="onClickReceive('mission', item)">
+                        <span class="num"><span class="num-add">+</span>${ item.num }</span>
+                        <span class="text" v-text="item.unit"></span>
+                        <span class="button">${ item.complete ? '点击领取' : '去完成' }</span>
+                    </div>
+                    <div class="m-list-item-text" v-text="item.name"></div>
+                </div>
+            </div>
+            <div class="section-footer">
+                <div class="progress-bar-container">
+                    <div class="progress-bar-label">当前进度</div>
+                    <div class="progress-bar">
+                        <div
+                            class="anchor"
+                            v-for="a in progressAnchorList"
+                            :disabled="a.className === 'received'"
+                            :key="a.rate"
+                            :style="{ left: a.rate + '%' }"
+                            :class="a.className">
+                            <div class="anchor-text">${ a.anchorText }</div>
+                            <div class="point-img" v-if="a.pointImg">
+                                <img :src="progress.pointImgMap[a.pointImg]" alt="">
+                            </div>
+                            <div class="anchor-tip-text" :class="{ floating: a.className === 'wait' }" :id="'progress-reward--' + a.id" v-show="a.tipText" @click="onClickReceive('schedule', a)">
+                                <p>${a.className === 'received' ? '已' : '免费'}领</p>
+                                <p v-text="a.tipText"></p>
+                            </div>
+                        </div>
+                        <div class="progress-bar-content" :style="{ width: rate + '%' }">
+                            <div class="blink-point"></div>
+                            <div class="blink-point-text anchor-text" v-show="blinkTextShow">${progress.current}剑鱼币</div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+        <!-- 福利三 -->
+        <div class="w section no-select section-fuli3">
+            <div class="section-header">
+                <div class="section-header-button">
+                    <img src="{{Msg "seo" "cdn"}}/frontRouter/pc/activity/image/202207/title-fuli3@2x.png" alt="">
+                </div>
+            </div>
+            <div class="section-content entniche-card-list">
+                <div class="entniche-card-item shangji"></div>
+                <div class="entniche-card-item zhuanjia"></div>
+            </div>
+            <div class="section-footer">
+                <div class="button-group">
+                    <button class="section-button learn-more" @click="toMemberPage">了解更多</button>
+                    <button class="section-button button-middle" @click="receiveFuli3">立即体验</button>
+                </div>
+                <div class="text">
+                    <p>满足企业多人使用 多场景赋能业务增长</p>
+                    <p>详情请致电咨询:400-108-6670</p>
+                </div>
+            </div>
+        </div>
+        <section class="w section activity-rules">
+            <div class="section-header">
+                <div class="section-header-text">
+                    <img src="{{Msg "seo" "cdn"}}/frontRouter/pc/activity/image/202207/activity-rule-text@2x.png" alt="">
+                </div>
+            </div>
+            <div class="section-content rules-list">
+                <div
+                    class="rules-item"
+                    v-for="(item, index) in rulesList"
+                    :key="index">
+                    <div class="rule-index">${ index + 1 }.</div>
+                    <div class="rule-text">${ item.text }</div>
+                </div>
+            </div>
+            <div class="section-footer">
+                <div class="footer-text">
+                    <img src="{{Msg "seo" "cdn"}}/frontRouter/pc/activity/image/202207/participate-in-text@2x.png" alt="">
+                </div>
+                <div class="copy-share-container">
+                    <span class="label-text">
+                        <span class="label-bold">分享活动:</span>
+                        <span>复制活动链接给好友</span>
+                    </span>
+                    <span class="content">
+                        <div class="content-text ellipsis" v-text="copyLinkText"></div>
+                        <button class="section-button button-small" @click="doCopy">复制链接</button>
+                    </span>
+                </div>
+            </div>
+        </section>
+        <!-- 顶部悬浮 -->
+        <div class="fixed-top top-timeline">
+            <div class="w timeline-list">
+                <div class="timeline-item yure" data-s-class="section-yure" v-show="activeState === 'waiting' || activeState === 'yureing'">
+                    <div class="t-left">预热福利</div>
+                    <div class="t-right">
+                        <div class="t-r-top">7天超级订阅限量领</div>
+                        <div class="t-r-bottom">
+                            <div class="t-r-b-l2" v-text="timeDuration.yure"></div>
+                            <div class="t-r-b-r2" v-text="calcYuReTopText"></div>
+                        </div>
+                    </div>
+                </div>
+                <div class="timeline-item fuli1" data-s-class="section-fuli1">
+                    <div class="t-left">福利一</div>
+                    <div class="t-right">
+                        <div class="t-r-top">百万补贴限量抢 支付立减</div>
+                        <div class="t-r-bottom" v-if="activeState === 'waiting' || activeState === 'yureing'">
+                            <div class="t-r-b-l">距开始</div>
+                            <div class="t-r-b-r" v-text="lastTimeText"></div>
+                        </div>
+                        <div class="t-r-bottom" v-else>
+                            <div class="t-r-b-l2" v-text="timeDuration.active"></div>
+                            <div class="t-r-b-r2" v-text="activeState === 'ended' ? '已结束' : '进行中'"></div>
+                        </div>
+                    </div>
+                </div>
+                <div class="timeline-item fuli2" data-s-class="section-fuli2">
+                    <div class="t-left">福利二</div>
+                    <div class="t-right">
+                        <div class="t-r-top">做任务 得2个月超级订阅</div>
+                        <div class="t-r-bottom" v-if="activeState === 'waiting' || activeState === 'yureing'">
+                            <div class="t-r-b-l">距开始</div>
+                            <div class="t-r-b-r" v-text="lastTimeText"></div>
+                        </div>
+                        <div class="t-r-bottom" v-else>
+                            <div class="t-r-b-l2" v-text="timeDuration.active"></div>
+                            <div class="t-r-b-r2" v-text="activeState === 'ended' ? '已结束' : '进行中'"></div>
+                        </div>
+                    </div>
+                </div>
+                <div class="timeline-item fuli3" data-s-class="section-fuli3">
+                    <div class="t-left">福利三</div>
+                    <div class="t-right">
+                        <div class="t-r-top">大会员钜惠 购买送时长</div>
+                        <div class="t-r-bottom" v-if="activeState === 'waiting' || activeState === 'yureing'">
+                            <div class="t-r-b-l">距开始</div>
+                            <div class="t-r-b-r" v-text="lastTimeText"></div>
+                        </div>
+                        <div class="t-r-bottom" v-else>
+                            <div class="t-r-b-l2" v-text="timeDuration.active"></div>
+                            <div class="t-r-b-r2" v-text="activeState === 'ended' ? '已结束' : '进行中'"></div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+        <!-- 右侧悬浮 -->
+        <div class="fixed-right">
+            <button class="fixed-action-button" @click="scrollTo('.activity-rules')">活动<br />规则</button>
+            <button class="fixed-action-button" @click="dialog.myReward = true">我的<br />奖励</button>
+        </div>
+        <!-- 奖励 table -->
+        <el-dialog title="我的奖励" class="no-select reward-section" :lock-scroll="false" append-to-body :visible.sync="dialog.myReward">
+            <div class="reward-card section-card">
+                <div class="reward-list-header tr">
+                    <div class="td">奖品名称</div>
+                    <div class="td">获取时间</div>
+                    <div class="td">获取方式</div>
+                    <div class="td">操作</div>
+                </div>
+                <div class="table-line"></div>
+                <div class="reward-list">
+                    <div
+                        class="reward-list-item tr"
+                        v-for="item in rewardList"
+                        :key="item.id">
+                        <div class="r-l-i-name td">
+                            <span class="j-icon" :class="'icon-' + item.icon"></span>
+                            <span v-text="item.rewardText"></span>
+                        </div>
+                        <div class="r-l-i-receive-time td" v-text="item.receiveTime"></div>
+                        <div class="r-l-i-receive-from td" v-text="item.receiveFrom"></div>
+                        <div class="r-l-i-action td">
+                            <button class="reward-action-button" @click="onClickListItem(item)">查看</button>
+                        </div>
+                    </div>
+                    <div v-show="rewardList.length === 0" class="reward-empty">暂未获得奖励,快去完成任务吧</div>
+                </div>
+            </div>
+        </el-dialog>
+    </div>
+</div>
+<!--S-弹窗-->
+<div class="modal fade in" id="active-tip-modal" tabindex="-1" role="dialog" aria-labelledby="active-tip-success"
+     aria-hidden="true">
+  <div class="modal-dialog active-tip--code">
+    <div class="close-dialog-icon" data-dismiss="modal" id="dialog-close--code">
+      <img src='{{Msg "seo" "cdn"}}/common-module/active/2022.5.20/close-red.png?v={{Msg "seo" "version"}}' alt="x">
+    </div>
+    <img class="code-img" src='/qr?url=%2fstl%2fmayActive' alt="扫一扫">
+    <p>
+      微信扫一扫,关注剑鱼标讯
+      <br>
+      <span>使用免费订阅</span>
+    </p>
+    <img class="bg-image" src='{{Msg "seo" "cdn"}}/common-module/active/2022.5.20/qrCodeBg.png?v={{Msg "seo" "version"}}' alt="扫一扫">
+  </div>
+  <div class="modal-dialog active-tip--over">
+    <div class="close-dialog-icon" data-dismiss="modal" id="dialog-icon--over" style="display: none">
+      <img src='{{Msg "seo" "cdn"}}/common-module/active/2022.5.20/close.png?v={{Msg "seo" "version"}}' alt="x">
+    </div>
+    <h4>活动结束提醒</h4>
+    <img width="148" src='{{Msg "seo" "cdn"}}/common-module/active/2022.5.20/empty.png?v={{Msg "seo" "version"}}' alt="活动已结束">
+    <p>
+      对不起,该活动已结束
+      <br>
+      可前往参加“邀请领好礼活动
+    </p>
+    <button data-dismiss="modal" id="dialog-button--over">立即前往</button>
+  </div>
+  <div class="modal-dialog active-tip--success">
+    <h5 class="text-gradient-red">领取成功</h5>
+    <p>
+      恭喜成功领取 <i class="text-give-day">7天</i> 超级订阅
+      <br>
+      <span>可在“我的奖励”中查看</span>
+    </p>
+    <button data-dismiss="modal" id="dialog-button--success">我知道了</button>
+    <img class="bg-image" src='{{Msg "seo" "cdn"}}/common-module/active/2022.7/dialog-bg@2x.png?v={{Msg "seo" "version"}}' alt="领取成功">
+  </div>
+</div>
+<!--E-弹窗-->
+<!-- 用户留资 -->
+<div id="vue-collect-user-info"></div>
+<script src='{{Msg "seo" "cdn"}}/js/jquery.cookie.js?v={{Msg "seo" "version"}}' type="text/javascript"></script>
+<script src='{{Msg "seo" "cdn"}}/js/public-nav.js?v={{Msg "seo" "version"}}' type="text/javascript"></script>
+<script>
+  $(function () {
+    haslogin({{.T.logid}});
+  })
+</script>
+<script src="//cdn-common.jianyu360.com/cdn/lib/vue/2.6.14/vue.min.js"></script>
+<script src="//cdn-common.jianyu360.com/cdn/lib/element-ui/2.15.7/lib/index.js"></script>
+<script src="//cdn-common.jianyu360.com/cdn/lib/moment/2.29.1/min/moment.min.js"></script>
+<script src="{{Msg "seo" "cdn"}}/big-member/js/utils.js?v={{Msg "seo" "version"}}"></script>
+<script src='{{Msg "seo" "cdn"}}/common-module/public/js/china-map-data.js?v={{Msg "seo" "version"}}'></script>
+<script src='{{Msg "seo" "cdn"}}/common-module/selector/js/static-data.js?v={{Msg "seo" "version"}}'></script>
+<script src='{{Msg "seo" "cdn"}}/js/pc-collect-user-info.js?v={{Msg "seo" "version"}}'></script>
+<script src="{{Msg "seo" "cdn"}}/frontRouter/pc/activity/js/task-202207.js?v={{Msg "seo" "version"}}"></script>
+<!--S-百度统计-->
+{{include "/common/pcbottom.html"}}
+{{include "/common/baiducc.html"}}
+<!--E-百度统计-->
+</body>
+</html>

+ 317 - 0
src/web/templates/frontRouter/wx/activity/sess/task-202207.html

@@ -0,0 +1,317 @@
+<!DOCTYPE html>
+<html lang="zh-CN" style="font-size: 50px;">
+
+<head>
+    <title>剑鱼超级会员节</title>
+
+    {{include "/big-member/wx/meta.html"}}
+
+    <!--S-当前页面的css资源-->
+    <link rel="stylesheet" href=//cdn-common.jianyu360.com/cdn/lib/reset-css/5.0.1/reset.min.css />
+    <link rel="stylesheet" href=//cdn-common.jianyu360.com/cdn/lib/vant/2.12.24/lib/index.css />
+    <link rel="stylesheet" href=//cdn-common.jianyu360.com/cdn/lib/vant/2.12.24/lib/icon/local.css />
+    <link rel="stylesheet" href='{{Msg "seo" "cdn"}}/big-member/weixin/css/public.css?v={{Msg "seo" "version"}}'>
+    <link rel="stylesheet" href='{{Msg "seo" "cdn"}}/big-member/weixin/css/j-icons.css?v={{Msg "seo" "version"}}'>
+    <link rel="stylesheet" href='{{Msg "seo" "cdn"}}/common-module/active/2022.7/task-common.css?v={{Msg "seo" "version"}}' />
+    <link rel="stylesheet" href='{{Msg "seo" "cdn"}}/common-module/active/2022.7/task-202207.css?v={{Msg "seo" "version"}}' />
+    <script src='{{Msg "seo" "cdn"}}/big-member/js/rem.js?v={{Msg "seo" "version"}}'></script>
+    <!--E-当前页面的css资源-->
+    <style>
+        .header-banner {
+            margin-top: -0.6rem;
+        }
+    </style>
+</head>
+
+<body>
+    <div class="j-container app">
+        {{include "/big-member/header.html"}}
+        <div class="j-main" id="main-app" v-cloak>
+            <div class="activity-rules-button" id="activity-rules-button" v-show="false" @click="dialogShow('rule', true)">规则</div>
+            <div class="header-banner">
+                <img class="header-banner-img" src="{{Msg "seo" "cdn"}}/common-module/active/2022.7/header-banner.png" alt="">
+            </div>
+            <div class="content-container">
+                <!-- 预热 -->
+                <section class="section no-select section-yure" v-show="yureSectionShow">
+                    <div class="section-header">
+                        <div class="section-header-button">
+                            <img src="{{Msg "seo" "cdn"}}/common-module/active/2022.7/title-yure@2x.png" alt="">
+                        </div>
+                    </div>
+                    <div class="section-content">
+                        <img src="{{Msg "seo" "cdn"}}/common-module/active/2022.7/content-yure@2x.png" alt="">
+                        <div class="content-info">
+                            <div class="c-info-text" v-html="yureInfo.tipText"></div>
+                            <button
+                                class="c-info-button section-button button-small"
+                                @click="receiveYuReCoupon"
+                                :disabled="yureInfo.buttonDisabled"
+                                v-show="yureButtonShow"
+                                v-text="yureInfo.buttonText"></button>
+                        </div>
+                    </div>
+                </section>
+                <!-- 更多活动即将开启 -->
+                <div class="section no-select section-more-activities" v-show="yureSectionShow">
+                    <div class="section-header">
+                        <div class="header-text">
+                            <img src="{{Msg "seo" "cdn"}}/common-module/active/2022.7/more-fuli-text@2x.png" alt="">
+                        </div>
+                    </div>
+                </div>
+                <!-- 福利一 -->
+                <div class="section no-select section-fuli1">
+                    <div class="section-header">
+                        <div class="section-header-button">
+                            <img src="{{Msg "seo" "cdn"}}/common-module/active/2022.7/title-fuli1@2x.png" alt="">
+                        </div>
+                    </div>
+                    <div class="section-content coupon-list">
+                        <div
+                            v-for="item in couponList"
+                            :key="item.id"
+                            class="coupon-item">
+                            <div class="coupon-title">满<span v-text="item.Full"></span>可用</div>
+                            <div class="coupon-value"><span class="num" v-text="item.Reduce">50</span>元</div>
+                            <button class="section-button button-small" @click="receiveActiveCoupon([item])" v-text="receiveActiveButtonText(item)"></button>
+                            <div class="coupon-text" v-text="item.tipText"></div>
+                        </div>
+                    </div>
+                    <div class="section-footer">
+                        <button class="section-button button-middle" v-show="onKeyReceiveShow" :disabled="couponList.length === 0" @click="receiveActiveCoupon(couponList)">一键领取</button>
+                    </div>
+                </div>
+                <!-- 福利二 -->
+                <div class="section no-select section-fuli2 progress-section">
+                    <div class="section-header">
+                        <div class="section-header-button">
+                            <img src="{{Msg "seo" "cdn"}}/common-module/active/2022.7/title-fuli2@2x.png" alt="">
+                        </div>
+                    </div>
+                    <div class="section-content mission-list" ref="missions">
+                        <img src="/common-module/active/2022.7/gift-box.png" alt="" class="mission-list-img">
+                        <div
+                            class="mission-list-item floating"
+                            :class="{ complete: item.complete, hide: item.hide, [item.id]: true, [item.className]: true }"
+                            v-for="item in missionsList"
+                            :id="'bubble-' + item.id"
+                            :style="{ left: item.x + 'rem', top: item.y + 'rem' }"
+                            @click="onClickReceive('mission', item)"
+                            :key="item.id">
+                            <div class="m-list-item-bg">
+                                <span class="num"><span class="num-add">+</span>${ item.num }</span>
+                                <span class="text" v-text="item.unit"></span>
+                                <span class="button" :id="'bubble-button--' + item.id">${ item.complete ? '点击领取' : '去完成' }</span>
+                            </div>
+                            <div class="m-list-item-text" v-text="item.name"></div>
+                        </div>
+                    </div>
+                    <div class="section-footer">
+                        <div class="progress-bar-container">
+                            <div class="progress-bar">
+                                <div
+                                    class="anchor"
+                                    v-for="a in progressAnchorList"
+                                    :key="a.rate"
+                                    :style="{ left: a.rate + '%' }"
+                                    :class="a.className">
+                                    <div class="anchor-text">${ a.anchorText }</div>
+                                    <div class="point-img" v-if="a.pointImg">
+                                        <img :src="progress.pointImgMap[a.pointImg]" alt="">
+                                    </div>
+                                    <div class="anchor-tip-text" v-show="a.tipText && false">
+                                        <p>免费领</p>
+                                        <p v-text="a.tipText"></p>
+                                    </div>
+                                </div>
+                                <div class="progress-bar-content" :style="{ width: rate + '%' }">
+                                    <div class="blink-point"></div>
+                                    <div class="blink-point-text anchor-text" v-show="blinkTextShow">${progress.current}剑鱼币</div>
+                                </div>
+                            </div>
+                        </div>
+                        <div class="progress-action-list">
+                            <button
+                                class="progress-action-button"
+                                :class="{ pointer: a.className === 'wait' }"
+                                :disabled="a.className === 'received'"
+                                v-for="(a, index) in progressAnchorList"
+                                v-if="a.tipText"
+                                :id="'progress-reward--' + a.id"
+                                @click="onClickReceive('schedule', a)"
+                                :key="index">${a.className === 'received' ? '已' : '免费'}领${a.tipText}</button>
+                        </div>
+                    </div>
+                </div>
+                <!-- 福利三 -->
+                <div class="section section-fuli3">
+                    <div class="section-header">
+                        <div class="section-header-button">
+                            <img src="{{Msg "seo" "cdn"}}/common-module/active/2022.7/title-fuli3@2x.png" alt="">
+                        </div>
+                    </div>
+                    <div class="section-content entniche-card-list">
+                        <div class="entniche-card-item shangji"></div>
+                        <div class="entniche-card-item zhuanjia"></div>
+                    </div>
+                    <div class="section-footer">
+                        <div class="button-group">
+                            <button class="section-button learn-more" @click="toMemberPage">了解更多</button>
+                            <button class="section-button button-middle" @click="receiveFuli3">立即体验</button>
+                        </div>
+                        <div class="text">
+                            <p>满足企业多人使用 多场景赋能业务增长</p>
+                            <p>详情请致电咨询:400-108-6670</p>
+                        </div>
+                    </div>
+                </div>
+                <!-- 顶部悬浮 -->
+                <div class="fixed-top top-timeline" v-show="false">
+                    <div class="timeline-list">
+                        <div class="timeline-item yure" data-s-class="section-yure" v-show="activeState === 'waiting' || activeState === 'yureing'">
+                            <div class="t-left">预热福利</div>
+                            <div class="t-right">
+                                <div class="t-r-bottom">
+                                    <div class="t-r-b-l2" v-text="timeDuration.yure"></div>
+                                    <div class="t-r-b-r2" v-text="calcYuReTopText"></div>
+                                </div>
+                            </div>
+                        </div>
+                        <div class="timeline-item fuli1" data-s-class="section-fuli1">
+                            <div class="t-left">福利一</div>
+                            <div class="t-right">
+                                <div class="t-r-bottom" v-if="activeState === 'waiting' || activeState === 'yureing'">
+                                    <div class="t-r-b-l">距开始</div>
+                                    <div class="t-r-b-r" v-text="lastTimeText"></div>
+                                </div>
+                                <div class="t-r-bottom" v-else>
+                                    <div class="t-r-b-l2" v-text="timeDuration.active"></div>
+                                    <div class="t-r-b-r2" v-text="activeState === 'ended' ? '已结束' : '进行中'"></div>
+                                </div>
+                            </div>
+                        </div>
+                        <div class="timeline-item fuli2" data-s-class="section-fuli2">
+                            <div class="t-left">福利二</div>
+                            <div class="t-right">
+                                <div class="t-r-bottom" v-if="activeState === 'waiting' || activeState === 'yureing'">
+                                    <div class="t-r-b-l">距开始</div>
+                                    <div class="t-r-b-r" v-text="lastTimeText"></div>
+                                </div>
+                                <div class="t-r-bottom" v-else>
+                                    <div class="t-r-b-l2" v-text="timeDuration.active"></div>
+                                    <div class="t-r-b-r2" v-text="activeState === 'ended' ? '已结束' : '进行中'"></div>
+                                </div>
+                            </div>
+                        </div>
+                        <div class="timeline-item fuli3" data-s-class="section-fuli3">
+                            <div class="t-left">福利三</div>
+                            <div class="t-right">
+                                <div class="t-r-bottom" v-if="activeState === 'waiting' || activeState === 'yureing'">
+                                    <div class="t-r-b-l">距开始</div>
+                                    <div class="t-r-b-r" v-text="lastTimeText"></div>
+                                </div>
+                                <div class="t-r-bottom" v-else>
+                                    <div class="t-r-b-l2" timeDuration.active></div>
+                                    <div class="t-r-b-r2" v-text="activeState === 'ended' ? '已结束' : '进行中'"></div>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+                <!-- 右侧悬浮 -->
+                <div class="fixed-right">
+                    <button class="fixed-action-button" @click="dialogShow('rule', true)">活动<br />规则</button>
+                    <button class="fixed-action-button" @click="dialog.myReward = true">我的<br />奖励</button>
+                </div>
+            </div>
+            <!-- 我的奖励 -->
+            <van-popup
+                v-model="dialog.myReward"
+                closeable
+                position="bottom"
+                class="reward-section"
+                round
+                get-container="body"
+                :style="{ maxHeight: '60%' }">
+                <section class="reward-card-container j-container no-select">
+                    <div class="r-header text-gradient-red"><div class="text-gradient-red">我的奖励</div></div>
+                    <div class="reward-card j-main section-card">
+                        <div class="reward-list" :class="{ empty: rewardList.length === 0 }">
+                            <div
+                                class="reward-list-item"
+                                v-for="item in rewardList"
+                                @click="onClickListItem(item)"
+                                :key="item.id">
+                                <span class="r-l-i-l j-icon-bg" :class="'icon-bg-' + item.icon"></span>
+                                <div class="r-l-i-c">
+                                    <div class="r-l-i-c-t">
+                                        <span class="reward-text" v-text="item.rewardText"></span>
+                                        <div class="receive-from" v-text="item.receiveFrom"></div>
+                                    </div>
+                                    <div class="receive-time" v-text="item.receiveTime"></div>
+                                </div>
+                                <div class="r-l-i-action">
+                                    <van-icon name="arrow"></van-icon>
+                                </div>
+                            </div>
+                            <div class="reward-empty" v-if="rewardList.length === 0">暂未获得奖励,快去完成任务吧</div>
+                        </div>
+                    </div>
+                </section>
+            </van-popup>
+            <!--S-弹窗-->
+            <van-popup id="active-tip-modal" v-model="dialog.show" :data-modal-type="dialog.type" :close-on-click-overlay="dialog.type !== 'over'">
+              <div v-show="dialog.type === 'rule'" class="modal-dialog active-tip--rule" :class="{max: getScreenMax}">
+                <h5 class="text-gradient-red">活动规则</h5>
+                <div class="rule-content">
+                  <div
+                    class="rule-item"
+                    v-for="(item, index) in rulesList"
+                    :key="index">
+                    <div class="rule-index">${ index + 1 }.</div>
+                    <div class="rule-text">${ item.text }</div>
+                  </div>
+                </div>
+                <button @click="dialogShow('rule', false)" id="dialog-button--rule">我知道了</button>
+                <img class="bg-image" src='{{Msg "seo" "cdn"}}/common-module/active/2022.7/dialog-bg-big@2x.png?v={{Msg "seo" "version"}}' alt="扫一扫">
+              </div>
+              <div v-show="dialog.type === 'over'" class="modal-dialog active-tip--over">
+                <div class="close-dialog-icon" @click="dialog.show = false" id="dialog-icon--over" v-if="!forbidClose">
+                  <img src='{{Msg "seo" "cdn"}}/common-module/active/2022.5.20/close.png?v={{Msg "seo" "version"}}' alt="x">
+                </div>
+                <h4>活动结束提醒</h4>
+                <img width="148" src='{{Msg "seo" "cdn"}}/common-module/active/2022.5.20/empty.png?v={{Msg "seo" "version"}}' alt="活动已结束">
+                <p>
+                  对不起,该活动已结束
+                  <br>
+                  可前往参加“邀请领好礼活动
+                </p>
+                <button @click="onClickReceive('', { id: 'invite' })" id="dialog-button--over">立即前往</button>
+              </div>
+              <div v-show="dialog.type === 'success'" class="modal-dialog active-tip--success">
+                <h5 class="text-gradient-red">领取成功</h5>
+                <p>
+                  恭喜成功领取<i style="font-weight: bold">${dialog.giftMonth}个月</i>超级订阅
+                  <br>
+                  <span>可在“我的奖励”中查看</span>
+                </p>
+                <button @click="dialogShow('success', false)" id="dialog-button--success">我知道了</button>
+                <img class="bg-image" src='{{Msg "seo" "cdn"}}/common-module/active/2022.7/dialog-bg@2x.png?v={{Msg "seo" "version"}}' alt="领取成功">
+              </div>
+            </van-popup>
+            <!--E-弹窗-->
+        </div>
+    </div>
+
+    <script src=//cdn-common.jianyu360.com/cdn/lib/vue/2.6.11/vue.min.js> </script>
+    <script src=//cdn-common.jianyu360.com/cdn/lib/vant/2.12.24/lib/vant.min.js> </script>
+    <script src=//cdn-common.jianyu360.com/cdn/lib/jquery/3.6.0/jquery.min.js> </script>
+    <script src=//cdn-common.jianyu360.com/cdn/lib/moment/2.29.1/min/moment.min.js></script>
+    {{include "/big-member/commonjs.html"}}
+    <script src='{{Msg "seo" "cdn"}}/common-module/public/js/utils.js?v={{Msg "seo" "version"}}'></script>
+    <script src='{{Msg "seo" "cdn"}}/common-module/active/2022.7/task-202207.js?v={{Msg "seo" "version"}}'></script>
+    {{include "/common/baiducc.html"}}
+</body>
+
+</html>

+ 11 - 1
src/web/templates/pc/biddetail_rec.html

@@ -1450,7 +1450,9 @@ var ucbs_source="pc_rec",ucbsId="{{.T.obj.ucbsId}}";
 		};
 	</script>
 	<script type="text/javascript">
-		var canRead = location.href.indexOf('mailprivate') > -1 || {{.T.canRead}}
+    var pathname = location.pathname
+    var entService = pathname.indexOf('entservice') !== -1
+		var canRead = location.href.indexOf('mailprivate') > -1 || {{.T.canRead}} || entService
     // 免费用户每日查看三次
     if(!(goTemplateData.params.obj.subtype == '采购意向' || goTemplateData.params.obj.subtype == '拟建') && !canRead) {
       $('#tip-title').text('免费查看更多公告')
@@ -1464,6 +1466,14 @@ var ucbs_source="pc_rec",ucbsId="{{.T.obj.ucbsId}}";
 
 		//是否显示遮罩层
 		function checkShowDialog (res) {
+      // 企业级用户不显示广告
+      if (entService) {
+        $('.lead-btn-nj').show()
+        $('.tabfat').show()
+        $(".recoveryfat").show()
+        $('.free-download').hide()
+        return 
+      }
 			var bidmember = false
 			var entniche = false
 			var vip = 0

+ 3 - 3
src/web/templates/pc/supsearch.html

@@ -928,7 +928,7 @@ var IframeOnClick = {
             </span>
           </div>
           <!--附件-->
-          <div class="attachment-filter clearfix" style="display: none;">
+          <div class="attachment-filter clearfix">
             <div class="leftTitle">
               附件:
             </div>
@@ -1222,7 +1222,7 @@ var IframeOnClick = {
           <div style="display: flex;">
             <div class="save-value-bg" v-if="curFilter.price"><span>价格区间:</span>${curFilter.price}</div>
             <div class="save-value-bg" v-if="curFilter.publishTime"><span>发布时间:</span>${curFilter.publishTime}</div>
-            <div class="save-value-bg" style="display: none;" v-if="curFilter.fileExists != '全部'"><span>附件:</span>${curFilter.fileExists}</div>
+            <div class="save-value-bg" v-if="curFilter.fileExists != '全部'"><span>附件:</span>${curFilter.fileExists}</div>
           </div>
           <div class="save-value-bg" v-if="curFilter.region"><span>项目地区:</span>${curFilter.region}</div>
           <div class="save-value-bg" v-if="curFilter.infoType"><span>信息类型:</span>${curFilter.infoType}</div>
@@ -1258,7 +1258,7 @@ var IframeOnClick = {
                 <p class="f-l-c-item">
                   <span v-if="item.minprice || item.maxprice">价格区间:<em class="i-value">${formatPriceScope(item.minprice, item.maxprice)}</em></span>
                   <span v-if="item.publishtime">发布时间:<em class="i-value">${formatPushTime(item.publishtime)}</em></span>
-                  <span style="display: none;" v-if="item.fileExists != 0">附件:<em class="i-value">${formatAttach(item.fileExists)}</em></span>
+                  <span v-if="item.fileExists != 0">附件:<em class="i-value">${formatAttach(item.fileExists)}</em></span>
                 </p>
                 <p class="f-l-c-item" v-if="item.area || item.city">项目地区:<em class="i-value">${formatRegion(item.area,item.city)}</em></p>
                 <p class="f-l-c-item" v-if="item.subtype">信息类型:<em class="i-value">${formatInfoType(item.subtype)}</em></p>

+ 1 - 1
src/web/templates/weixin/historypush.html

@@ -812,7 +812,7 @@
                                     </span>
                                 </template>
                             </van-cell>
-                            <van-cell center style="display: none; height: auto;"  @click="moreFiltersItemShow('fileItem', '附件')">
+                            <van-cell center style="height: auto;"  @click="moreFiltersItemShow('fileItem', '附件')">
                               <template #title>
                                   <span v-if="screenShow" class="noticeText">附件</span>
                                   <span v-else class="rootstyletitle">