shorturl.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505
  1. package front
  2. import (
  3. "database/sql"
  4. "fmt"
  5. "jfw/config"
  6. "jfw/jyutil"
  7. "jfw/public"
  8. "jfw/wx"
  9. "log"
  10. "math/rand"
  11. . "mongodb"
  12. "net/url"
  13. "qfw/util"
  14. "qfw/util/elastic"
  15. "qfw/util/jy"
  16. "qfw/util/redis"
  17. "regexp"
  18. "strconv"
  19. "strings"
  20. "time"
  21. "github.com/SKatiyar/qr"
  22. "github.com/go-xweb/xweb"
  23. "go.mongodb.org/mongo-driver/bson"
  24. )
  25. type Short struct {
  26. *xweb.Action
  27. article xweb.Mapper `xweb:"/article/(\\w+)/(.*).html"` //([pm])
  28. qr xweb.Mapper `xweb:"/biddetail/(\\w+)/qr/(.+)"`
  29. replication xweb.Mapper `xweb:"/front/shorturl/replication"` //用户复制操作记录入库
  30. }
  31. var mobileReg = regexp.MustCompile("(?i)(Android|Mobile|Phone)")
  32. var DateFullLayout = "2006-01-02 15:04:05"
  33. var Map_stype = map[string]bool{
  34. "content": true,
  35. "bdprivate": true,
  36. "mailprivate": true,
  37. "bdcontent": true,
  38. "indexcontent": true,
  39. }
  40. func (s *Short) Article(stype, id string) error {
  41. //先判断是否有session
  42. source := s.GetString("source")
  43. disWord := s.GetString("disWord")
  44. aboutUrl := "/swordfish/about"
  45. //是否已经检查过,默认是检查过-true,分享过来的是未检查过-false
  46. // checkIsSubscribeFlag := true
  47. // if source == "app_infocontentshare" || source == "wx_infocontentshare" {
  48. // checkIsSubscribeFlag = false
  49. // }
  50. from_userid := ""
  51. if source != "" {
  52. aboutUrl += "?source=" + source
  53. if strings.Contains(source, "wx_infocontentshare") {
  54. decodeArr := util.DecodeArticleId2ByCheck(id)
  55. if len(decodeArr) > 1 {
  56. from_userid = se.Encode2Hex(GetUserId(decodeArr[1])) //加密用户userid
  57. }
  58. } else if strings.Contains(source, "app_infocontentshare") {
  59. if from := s.GetString("from"); from != "" {
  60. from_userid = from
  61. }
  62. }
  63. aboutUrl += "&from=" + from_userid
  64. }
  65. bm := false
  66. userId, _ := s.GetSession("userId").(string)
  67. if !Map_stype[stype] {
  68. s.Redirect("/not/nottype", 302)
  69. return nil
  70. } else if stype == "content" || stype == "bdcontent" {
  71. if s.Session().Get("userId") == nil {
  72. if s.GetString("state") == "wx" {
  73. //微信跳回来的
  74. code := s.GetString("code")
  75. if code != "" {
  76. openid := jyutil.Getopenid(code)
  77. if openid != "" {
  78. isSubscribe := CheckUserIsSubscribe(openid)
  79. if isSubscribe {
  80. FindUserAndCreateSess(openid, s.Session(), "wx", false)
  81. }
  82. }
  83. }
  84. } else {
  85. if public.CheckWxBrowser(s.Request) {
  86. //所有参数都不再使用,跳到微信验证用户
  87. return s.Redirect(fmt.Sprintf(config.Wxoauth, url.QueryEscape(s.Site()+s.Url()), "wx"), 302)
  88. }
  89. }
  90. }
  91. if disWord != "" {
  92. redisDis := redis.GetStr("other", "DIS_"+disWord[1:])
  93. if redisDis != "" {
  94. suffix := disWord[len(disWord)-3 : len(disWord)]
  95. //公告三级页处理
  96. if suffix == suffix_msgt {
  97. effectiveTimeStr := strings.Split(redisDis, "##")[3]
  98. effectiveTime, _ := strconv.ParseInt(effectiveTimeStr, 10, 64)
  99. //是否计算佣金
  100. if time.Now().Unix() <= effectiveTime {
  101. belongUserId := strings.Split(redisDis, "##")[1]
  102. //if (belongUserId != userId) {
  103. if public.Mysql.ExecTx("口号使用", func(tx *sql.Tx) bool {
  104. //口号是否使用过
  105. wordInfo := public.Mysql.Find("dis_word", map[string]interface{}{"userId": userId, "password": disWord}, "id", "", 0, 0)
  106. if len((*wordInfo)) == 0 {
  107. //新增口号使用
  108. wordInfo = public.Mysql.Find("dis_word", map[string]interface{}{"userId": userId}, "id,start_time,stop_time", "stop_time", 0, 1)
  109. start_time := time.Now().Format(DateFullLayout)
  110. termValidityInt, _ := strconv.Atoi(fmt.Sprint(config.Sysconfig["termValidity"]))
  111. stop_time := TimeProcessing(time.Now().Format(DateFullLayout), termValidityInt).Format(DateFullLayout)
  112. insert := map[string]interface{}{
  113. "password": disWord,
  114. "userId": userId,
  115. "belong_userid": belongUserId,
  116. "start_time": start_time,
  117. "stop_time": stop_time,
  118. }
  119. insert_1 := public.Mysql.InsertByTx(tx, "dis_word", insert) //口号使用表
  120. log.Println("插入口号使用表", insert_1)
  121. from_userid = se.Encode2Hex(belongUserId)
  122. }
  123. return true
  124. }) {
  125. }
  126. }
  127. //}
  128. }
  129. }
  130. }
  131. client := s.Header("User-Agent")
  132. bm = mobileReg.MatchString(client)
  133. if s.Session().Get("userId") == nil { //} && !regclient.MatchString(client) { //没有用户session //搜索引擎让过
  134. s.Session().Set("referer", s.Request.RequestURI)
  135. if bm { //是否是移动端访问
  136. s.Redirect(aboutUrl, 302)
  137. } else {
  138. if stype == "bdcontent" {
  139. var retMap = make(map[string]interface{})
  140. stype = "content"
  141. _id := util.CommonDecodeArticle(stype, id)[0]
  142. _, _, _, obj := pcVRT(_id, "", true)
  143. if obj != nil && len(obj) > 0 {
  144. retMap["_id"] = id
  145. retMap["title"], _ = obj["title"].(string)
  146. retMap["area"], _ = obj["area"].(string)
  147. retMap["subtype"], _ = obj["subtype"].(string)
  148. retMap["subscopeclass"], _ = obj["s_subscopeclass"].(string)
  149. retMap["publishtime"] = util.IntAll(obj["publishtime"])
  150. }
  151. s.T["shareid"] = config.Seoconfig["baiduSEM-p"].(string)
  152. s.T["logid"] = config.Seoconfig["baiduSEM-p"].(string)
  153. s.T["obj"] = retMap
  154. s.Render("/pc/biddetail_bd.html", &s.T)
  155. } else {
  156. s.Redirect("/notin/page", 302)
  157. }
  158. }
  159. return nil
  160. }
  161. if stype == "bdcontent" {
  162. stype = "content"
  163. }
  164. }
  165. ssOpenid := s.Session().Get("s_m_openid")
  166. var res *map[string]interface{}
  167. if userId == "" && ssOpenid != nil {
  168. res, _ = mongodb.FindOneByField("user", bson.M{"s_m_openid": ssOpenid, "s_unionid": bson.M{"$ne": ssOpenid}}, `{"i_vip_status":1,"i_member_status":1,"s_m_phone":1,"s_phone":1}`)
  169. userId = BsonIdToSId((*res)["_id"])
  170. } else {
  171. //判断用户是否是vip
  172. res, _ = public.MQFW.FindById("user", userId, `{"i_vip_status":1,"i_member_status":1,"s_m_phone":1,"s_phone":1}`)
  173. }
  174. isVip, isMember, isEntniche, privatedata := false, false, false, false
  175. isVip = util.IntAll((*res)["i_vip_status"]) == 1 || util.IntAll((*res)["i_vip_status"]) == 2
  176. isMember = util.IntAll((*res)["i_member_status"]) > 0
  177. if phone, _ := util.If(util.ObjToString((*res)["s_phone"]) != "", util.ObjToString((*res)["s_phone"]), util.ObjToString((*res)["s_m_phone"])).(string); phone != "" {
  178. isEntniche = public.Mysql.CountBySql(`SELECT count(1) from entniche_user a INNER JOIN entniche_info b on (a.phone=? and a.power=1 and a.ent_id=b.id and b.status>0)`, phone) > 0
  179. privatedata = public.Mysql.CountBySql(`select count(1) from privatedata where phone = ?`, phone) > 0
  180. }
  181. if !isEntniche && privatedata {
  182. isEntniche = true
  183. }
  184. s.T["isVip"] = isVip
  185. s.T["isMember"] = isMember
  186. s.T["isEntniche"] = isEntniche
  187. if bm {
  188. //判断有没有取关,取关的话,跳转到关于剑鱼标讯页面
  189. if ssOpenid != nil && ssOpenid != "" {
  190. isSubscribe := CheckUserIsSubscribe(ssOpenid.(string))
  191. if !isSubscribe {
  192. return s.Redirect(aboutUrl, 302)
  193. }
  194. //之前sessionkeep.go中没有放userId,造成关注有问题
  195. if s.GetSession("userId") == nil {
  196. FindUserAndCreateSess(ssOpenid.(string), s.Session(), "wx", false)
  197. }
  198. }
  199. surl := s.GetString("url")
  200. kds := s.GetString("keywords")
  201. industry := s.GetString("industry")
  202. var shareopenid, sid string
  203. sid_openid := util.CommonDecodeArticle(stype, id)
  204. if len(sid_openid) == 0 {
  205. s.Redirect(aboutUrl, 302)
  206. return nil
  207. } else if len(sid_openid) > 1 {
  208. sid = sid_openid[0]
  209. shareopenid = sid_openid[1]
  210. } else {
  211. sid = sid_openid[0]
  212. }
  213. s.T["keywords"] = kds
  214. if shareopenid != "" {
  215. s.T["shareopenid"] = shareopenid
  216. }
  217. myopenid, _ := s.Session().Get("s_m_openid").(string)
  218. if myopenid == "" {
  219. myopenid = shareopenid
  220. s.T["openid"] = myopenid //"-1"
  221. } else {
  222. s.T["openid"] = se.EncodeString(myopenid) //"-1"
  223. }
  224. mynickname, _ := s.GetSession("s_nickname").(string)
  225. myavatar, _ := s.GetSession("s_avatar").(string)
  226. s.T["nickname"] = mynickname
  227. s.T["avatar"] = myavatar
  228. s.T["signature"] = wx.SignJSSDK(s.Site() + s.Url())
  229. var obj map[string]interface{}
  230. obj = wxvisitD(sid, userId, myopenid, isVip || isMember || isEntniche)
  231. if len(obj) > 0 {
  232. //获取打赏文案
  233. s.T["rewardText"], s.T["advertText"] = getRewardText()
  234. //纠错随机回复
  235. recoveryRight, _ := config.Sysconfig["recoveryRight"].([]interface{})
  236. recVal := rand.New(rand.NewSource(time.Now().UnixNano())).Intn(len(recoveryRight))
  237. s.T["recVal"] = util.ObjToString(recoveryRight[recVal])
  238. s.T["advertImg"] = config.Sysconfig["advertImg"]
  239. s.T["advertName"] = config.Sysconfig["advertName"]
  240. s.T["advertUrl"] = config.Sysconfig["advertUrl"]
  241. obj["industry"] = industry
  242. if ssOpenid != nil {
  243. obj["ucbsId"] = util.EncodeArticleId2ByCheck("ucbs#" + ssOpenid.(string) + "#" + id)
  244. }
  245. if obj["winnertel"] == nil && isbid(obj["subtype"]) {
  246. obj["winner_enttel"] = getwinnertel(obj["winner"])
  247. }
  248. if !(isVip || isMember || isEntniche) { //非会员不展示电话字段
  249. if obj["winnertel"] != nil {
  250. obj["winnertel"] = "无权限"
  251. }
  252. if obj["winner_enttel"] != "" {
  253. obj["winner_enttel"] = "无权限"
  254. }
  255. }
  256. s.T["obj"] = obj
  257. if obj["entidlist"] != nil { //大会员中标企业跳转至画像
  258. if winner := util.ObjToString(obj["winner"]); winner != "" {
  259. //临时更改为企业名称查询企业id
  260. rData := elastic.Get("qyxy", "qyxy", fmt.Sprintf(`{"query":{"bool":{"should":[{"term":{"company_name":"%s"}},{"term":{"hname":"%s"}}],"minimum_should_match":1}},"_source":["name","_id","capital","company_phone"],"size":1}`, winner, winner))
  261. if rData != nil && len(*rData) == 1 {
  262. if entId := util.ObjToString((*rData)[0]["_id"]); entId != "" {
  263. obj["entId"] = util.EncodeArticleId2ByCheck(util.ObjToString((*rData)[0]["_id"]))
  264. }
  265. }
  266. //s_winner := util.ObjToString(obj["s_winner"])
  267. //idObjs, _ := obj["entidlist"].([]interface{})
  268. //winnerId := ""
  269. //if names := strings.Split(s_winner, ","); len(names) > 1 {
  270. // index := 0
  271. // for i := 0; i < len(names); i++ {
  272. // if names[i] == winner {
  273. // index = i
  274. // break
  275. // }
  276. // }
  277. // if len(idObjs) > index {
  278. // winnerId = util.ObjToString(idObjs[index])
  279. // }
  280. //} else { //中标企业仅一个
  281. // if len(idObjs) > 0 {
  282. // winnerId = util.ObjToString(idObjs[0])
  283. // }
  284. //}
  285. //if winnerId != "" {
  286. // obj["entId"] = util.EncodeArticleId2ByCheck(winnerId)
  287. //}
  288. }
  289. }
  290. if from_userid != "" && se.Decode4Hex(from_userid) != "" && from_userid != userId && util.ObjToString(obj["subtype"]) != "拟建" { //分享开打的
  291. article_id := util.CommonDecodeArticle(stype, id)[0]
  292. key := fmt.Sprintf("integral_article_%s_%s_%s", article_id, from_userid, userId)
  293. if redis.Incr("other", key) == 1 {
  294. redis.SetExpire("other", key, 60*60*24)
  295. err := jy.Publish(public.Mgo_Log, config.Sysconfig["nsq"].(string), jy.Jyweb_article_open, se.Decode4Hex(from_userid), jy.Jywx_node1)
  296. if err != nil {
  297. log.Println("nsq队列写入失败-->", jy.Jyweb_article_open, se.Decode4Hex(from_userid))
  298. }
  299. }
  300. }
  301. s.T["advertcode"] = s.GetString("advertcode")
  302. content, _ := s.Render4Cache("/weixin/wxinfocontent_rec.html", &s.T)
  303. return s.SetBody(content)
  304. }
  305. if surl != "" {
  306. return s.Redirect(surl)
  307. }
  308. } else {
  309. sids := util.CommonDecodeArticle(stype, id)
  310. if len(sids) == 0 {
  311. s.Redirect("/notin/page", 302)
  312. return nil
  313. }
  314. sid := sids[0]
  315. catchKey := fmt.Sprintf("jypcdetail_%s_%v_%v_%v", sid, isVip, isEntniche, isMember)
  316. //缓存读取
  317. res := redis.Get("other", catchKey)
  318. if res == nil || res == "" {
  319. industry := s.GetString("industry")
  320. var shareid = s.GetString("id")
  321. if len(shareid) == 0 {
  322. shareid = "10"
  323. }
  324. s.T["logid"] = config.Seoconfig["jysskzy"].(string)
  325. s.T["shareid"] = se.EncodeString(shareid)
  326. s.T["keywords"] = s.GetString("kds")
  327. s.DisableHttpCache()
  328. po, bo, wo, obj := pcVRT(sid, industry, isVip || isMember || isEntniche)
  329. if obj != nil && len(obj) > 0 {
  330. href, _ := obj["href"].(string)
  331. href = strings.Replace(href, "\n", "", -1)
  332. if href != "" && !strings.HasPrefix(href, "http") {
  333. href = "http://" + href
  334. }
  335. if len(po) > 0 {
  336. s.T["projectOther"] = po
  337. }
  338. if len(bo) > 0 {
  339. s.T["buyerOther"] = bo
  340. }
  341. if len(wo) > 0 {
  342. s.T["winnerOther"] = wo
  343. }
  344. obj["url"] = href
  345. obj["industry"] = industry
  346. if ssOpenid != nil {
  347. obj["ucbsId"] = util.EncodeArticleId2ByCheck("ucbs#" + ssOpenid.(string) + "#" + id)
  348. }
  349. if obj["winnertel"] == nil && isbid(obj["subtype"]) {
  350. obj["winner_enttel"] = getwinnertel(obj["winner"])
  351. }
  352. if !(isVip || isMember || isEntniche) { //非会员不展示电话字段
  353. if obj["winnertel"] != nil {
  354. obj["winnertel"] = "无权限"
  355. }
  356. if obj["winner_enttel"] != "" {
  357. obj["winner_enttel"] = "无权限"
  358. }
  359. }
  360. s.T["obj"] = obj
  361. if obj["projectname"] != nil {
  362. s.SetSession("projectname", obj["projectname"])
  363. }
  364. if obj["entidlist"] != nil { //大会员中标企业跳转至画像
  365. winner := util.ObjToString(obj["winner"])
  366. s_winner := util.ObjToString(obj["s_winner"])
  367. idObjs, _ := obj["entidlist"].([]interface{})
  368. winnerId := ""
  369. if names := strings.Split(s_winner, ","); len(names) > 1 {
  370. index := 0
  371. for i := 0; i < len(names); i++ {
  372. if names[i] == winner {
  373. index = i
  374. break
  375. }
  376. }
  377. if len(idObjs) > index {
  378. winnerId = util.ObjToString(idObjs[index])
  379. }
  380. } else { //中标企业仅一个
  381. if len(idObjs) > 0 {
  382. winnerId = util.ObjToString(idObjs[0])
  383. }
  384. }
  385. if winnerId != "" {
  386. obj["entId"] = util.EncodeArticleId2ByCheck(winnerId)
  387. }
  388. }
  389. content, _ := s.Render4Cache("/pc/biddetail_rec.html", &s.T)
  390. timeout := 60 * 20
  391. if stype == "indexcontent" {
  392. timeout = 60 * 10
  393. }
  394. redis.Put("other", catchKey, string(content), timeout)
  395. return s.SetBody(content)
  396. }
  397. } else {
  398. return s.SetBody([]byte(res.(string)))
  399. }
  400. }
  401. return nil
  402. }
  403. //检查用户是否关注
  404. func CheckUserIsSubscribe(openid string) bool {
  405. user, ok := mongodb.FindOneByField("user", map[string]interface{}{
  406. "i_appid": 2,
  407. "s_m_openid": openid,
  408. "s_unionid": map[string]interface{}{"$ne": openid},
  409. }, `{"i_ispush":1}`)
  410. if ok && user != nil {
  411. if (*user)["_id"] == nil || util.IntAllDef((*user)["i_ispush"], 1) == 0 {
  412. return false
  413. } else {
  414. return true
  415. }
  416. }
  417. return false
  418. }
  419. func (s *Short) Qr(t, id string) error {
  420. w := s.ResponseWriter
  421. w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate")
  422. w.Header().Set("Pragma", "no-cache")
  423. w.Header().Set("Expires", "0")
  424. w.Header().Set("Content-Type", "image/png")
  425. kds := s.GetString("kds")
  426. industry := s.GetString("industry")
  427. param := "?scan_source=pc"
  428. if t == "force" {
  429. param += "&ispcforceshare=1"
  430. }
  431. if kds != "" {
  432. param += "&keywords=" + kds
  433. }
  434. if industry != "" {
  435. param += "&industry=" + industry
  436. }
  437. data := config.Sysconfig["webdomain"].(string) + "/article/content/" + id + ".html" + param
  438. r, _ := qr.Encode(data, qr.M)
  439. pngdat := r.PNG()
  440. _, err := w.Write(pngdat)
  441. return err
  442. }
  443. func (s *Short) Replication() {
  444. userId, OK := s.GetSession("userId").(string)
  445. if OK && userId != "" {
  446. mongodb.Save("copyaction", map[string]interface{}{
  447. "userid": userId,
  448. "createtime": time.Now().Unix(),
  449. "url": s.Request.Referer(),
  450. "client": s.Header("User-Agent"),
  451. })
  452. }
  453. }
  454. func isbid(typ interface{}) bool {
  455. if typ != nil {
  456. subtype := util.ObjToString(typ)
  457. if subtype == "中标" || subtype == "合同" || subtype == "成交" {
  458. return true
  459. }
  460. }
  461. return false
  462. }
  463. func getwinnertel(company interface{}) string {
  464. if company != nil {
  465. data, _ := public.Mgo_Ent.FindOne("winner_enterprise", map[string]interface{}{
  466. "company_name": util.ObjToString(company),
  467. })
  468. if (*data)["company_phone"] != nil {
  469. return util.ObjToString((*data)["company_phone"])
  470. }
  471. }
  472. return ""
  473. }
  474. func GetUserId(openid string) string {
  475. data, ok := public.MQFW.FindOne("user", map[string]interface{}{"s_m_openid": openid})
  476. if data != nil && len(*data) > 0 && ok {
  477. userid := BsonIdToSId((*data)["_id"])
  478. return userid
  479. }
  480. return ""
  481. }