article.go 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562
  1. package cygx
  2. import (
  3. "errors"
  4. "fmt"
  5. "github.com/PuerkitoBio/goquery"
  6. "hongze/hz_crm_api/models"
  7. "hongze/hz_crm_api/models/company"
  8. "hongze/hz_crm_api/models/cygx"
  9. "hongze/hz_crm_api/services"
  10. "hongze/hz_crm_api/services/alarm_msg"
  11. "hongze/hz_crm_api/utils"
  12. "html"
  13. "strconv"
  14. "strings"
  15. )
  16. func ArticlePublishDate(publishDate string) (newPublishDate string) {
  17. newPublishDate = strings.Replace(publishDate, "00:00:00", "", -1)
  18. newPublishDate = strings.Replace(newPublishDate, " ", "", -1)
  19. return
  20. }
  21. func GetReportContentTextSubNew(content string) (contentSub string, err error) {
  22. content = html.UnescapeString(content)
  23. doc, errdoc := goquery.NewDocumentFromReader(strings.NewReader(content))
  24. if errdoc != nil {
  25. err = errdoc
  26. return
  27. }
  28. docText := doc.Text()
  29. bodyRune := []rune(docText)
  30. bodyRuneLen := len(bodyRune)
  31. body := string(bodyRune[:bodyRuneLen])
  32. contentSub = body
  33. contentSub = strings.Replace(contentSub, "Powered by Froala Editor", "", -1)
  34. contentSub = strings.Replace(contentSub, " ", "", -1)
  35. contentSub = strings.Replace(contentSub, "<p data-f-id=\"pbf\" style=\"text-align: center; font-size: 14px; margin-top: 30px; opacity: 0.65; font-family: sanered by <a href=\"https://www.froala.com/wysiwyg-editor?pb=1\" title=\"Froala Editor\">Froala Editor</a></p>", "", -1)
  36. return
  37. }
  38. func ArticleComPanyLabelToStr(companyLabel []string) (label string) {
  39. for _, v := range companyLabel {
  40. label += v + "{|}"
  41. }
  42. label = strings.TrimRight(label, "{|}")
  43. return
  44. }
  45. // GetArticleStockMap 获取个股标签所对应的文章ID
  46. func GetArticleStockMap() (mapResp map[string]int, err error) {
  47. defer func() {
  48. if err != nil {
  49. go alarm_msg.SendAlarmMsg("获取个股标签所对应的文章ID失败"+err.Error(), 2)
  50. }
  51. }()
  52. list, err := cygx.GetArticleStock()
  53. if err != nil && err.Error() != utils.ErrNoRow() {
  54. return
  55. }
  56. mapResp = make(map[string]int, 0)
  57. if len(list) > 0 {
  58. //一对一精准匹配
  59. for _, v := range list {
  60. sliceSubjects := strings.Split(v.Stock, "/")
  61. if len(sliceSubjects) > 0 {
  62. for _, vSubject := range sliceSubjects {
  63. sliceKuohao := strings.Split(vSubject, "(") //过滤括号
  64. sliceXiahuaxian := strings.Split(sliceKuohao[0], "-") //过滤下划线
  65. subject := sliceXiahuaxian[0]
  66. mapResp[subject] = v.ArticleId
  67. }
  68. }
  69. }
  70. }
  71. return
  72. }
  73. // 处理文章来源类型
  74. func GetArticleSourcePlatform(SourcePlatform string) (sourcePlatformResp int) {
  75. //SourcePlatform string `description:"来源 'MOBILE:移动端小程序','PC:PC端小程序','CELUE:上海策略平台','WEB:查研观向网页版'"`
  76. if SourcePlatform == "MOBILE" || SourcePlatform == "PC" {
  77. sourcePlatformResp = 1
  78. } else if SourcePlatform == "WEB" {
  79. sourcePlatformResp = 2
  80. } else if SourcePlatform == "CELUE" {
  81. sourcePlatformResp = 3
  82. } else if SourcePlatform == "1" {
  83. sourcePlatformResp = 1
  84. } else if SourcePlatform == "2" {
  85. sourcePlatformResp = 2
  86. } else {
  87. sourcePlatformResp, _ = strconv.Atoi(SourcePlatform)
  88. }
  89. return
  90. }
  91. // 处理文章来源类型
  92. func GetArticleSourcePlatformText(sourcePlatformResp int) (sourcePlatformText string) {
  93. switch sourcePlatformResp {
  94. case 1:
  95. sourcePlatformText = "查研小程序"
  96. case 2:
  97. sourcePlatformText = "查研网页版"
  98. case 3:
  99. sourcePlatformText = "策略平台"
  100. case 5:
  101. sourcePlatformText = "研选小程序"
  102. case 6:
  103. sourcePlatformText = "研选网页版"
  104. default:
  105. sourcePlatformText = "查研小程序"
  106. }
  107. return
  108. }
  109. //func init() {
  110. // GetArticleSubjectLabelByArticleId([]int{9551, 9082})
  111. //}
  112. // 根据文章ID获取文章关联的产业名称
  113. func GetArticleIndustrialLabelByArticleId(articleIds []int) (respMap map[int][]string) {
  114. if len(articleIds) == 0 {
  115. return
  116. }
  117. var err error
  118. defer func() {
  119. if err != nil {
  120. go alarm_msg.SendAlarmMsg(fmt.Sprint("根据文章ID获取文章关联的产业名称失败 GetArticleIndustrialLabelByArticleId rticleIds: ", articleIds, err.Error()), 2)
  121. }
  122. }()
  123. list, e := cygx.GetIndustrialArticleGroupListByarticleIdsArr(articleIds)
  124. if e != nil && e.Error() != utils.ErrNoRow() {
  125. err = errors.New("GetIndustrialArticleGroupListByarticleIdsArr, Err: " + e.Error())
  126. return
  127. }
  128. respMap = make(map[int][]string, 0)
  129. for _, v := range list {
  130. respMap[v.ArticleId] = append(respMap[v.ArticleId], v.IndustryName)
  131. }
  132. return
  133. }
  134. // 根据文章ID获取文章关联的标的名称
  135. func GetArticleSubjectLabelByArticleId(articleIds []int) (respMap map[int][]string) {
  136. if len(articleIds) == 0 {
  137. return
  138. }
  139. var err error
  140. defer func() {
  141. if err != nil {
  142. go alarm_msg.SendAlarmMsg(fmt.Sprint("根据文章ID获取文章关联的产业名称 失败 GetArticleSubjectLabelByArticleId rticleIds: ", articleIds, err.Error()), 2)
  143. }
  144. }()
  145. list, e := cygx.GetSubjectArticleGroupListByarticleIdsArr(articleIds)
  146. if e != nil && e.Error() != utils.ErrNoRow() {
  147. err = errors.New("GetIndustrialArticleGroupListByarticleIdsArr, Err: " + e.Error())
  148. return
  149. }
  150. respMap = make(map[int][]string, 0)
  151. for _, v := range list {
  152. respMap[v.ArticleId] = append(respMap[v.ArticleId], v.SubjectName)
  153. }
  154. return
  155. }
  156. // 根据作者ID获取关联的文章下面的产业名称
  157. func GetArticleIndustrialLabelByDepartmentId(departmentIds []int) (respMap map[int][]string) {
  158. lenArr := len(departmentIds)
  159. if lenArr == 0 {
  160. return
  161. }
  162. var err error
  163. defer func() {
  164. if err != nil {
  165. go alarm_msg.SendAlarmMsg(fmt.Sprint("根据文章ID获取文章关联的产业名称失败 GetArticleIndustrialLabelByDepartmentId departmentIds: ", departmentIds, err.Error()), 2)
  166. }
  167. }()
  168. var condition string
  169. var pars []interface{}
  170. condition = " AND department_id IN(" + utils.GetOrmInReplace(lenArr) + ") ORDER BY publish_date DESC "
  171. pars = append(pars, departmentIds)
  172. //获取作者关联的文章
  173. listArticle, e := cygx.GetArticlList(condition, pars, 0, 9999)
  174. if e != nil && e.Error() != utils.ErrNoRow() {
  175. err = errors.New("GetArticlList, Err: " + e.Error())
  176. return
  177. }
  178. var articleIds []int
  179. for _, v := range listArticle {
  180. articleIds = append(articleIds, v.ArticleId)
  181. }
  182. //获取文章关联的产业
  183. list, e := cygx.GetIndustrialArticleGroupListByarticleIdsArr(articleIds)
  184. if e != nil && e.Error() != utils.ErrNoRow() {
  185. err = errors.New("GetIndustrialArticleGroupListByarticleIdsArr, Err: " + e.Error())
  186. return
  187. }
  188. respMap = make(map[int][]string, 0)
  189. artMap := make(map[int][]string)
  190. for _, v := range list {
  191. artMap[v.ArticleId] = append(respMap[v.ArticleId], v.IndustryName)
  192. }
  193. //建立作者与文章、产业的关系
  194. for _, v := range listArticle {
  195. if len(artMap[v.ArticleId]) == 0 {
  196. continue
  197. }
  198. respMap[v.DepartmentId] = append(respMap[v.DepartmentId], strings.Join(artMap[v.ArticleId], "/"))
  199. }
  200. return
  201. }
  202. // 处理文章、研选专栏的查询信息回显
  203. func HandleArticleAndYanxuanRecordList(items []*cygx.CygxArticleAndYanxuanRecordResp) (itemsResp []*cygx.UserInteraction, err error) {
  204. itemsResp = make([]*cygx.UserInteraction, 0)
  205. if len(items) > 0 {
  206. var articleIds []int // 文章ID
  207. var yanxuanSpecialIds []int // 研选专栏ID
  208. var sellerCompanyIds []int // 公司ID
  209. var mobiles []string // 手机号
  210. for _, v := range items {
  211. if v.Source == utils.CYGX_OBJ_ARTICLE {
  212. articleIds = append(articleIds, v.SourceId)
  213. }
  214. if v.Source == utils.CYGX_OBJ_YANXUANSPECIAL {
  215. yanxuanSpecialIds = append(yanxuanSpecialIds, v.SourceId)
  216. }
  217. sellerCompanyIds = append(sellerCompanyIds, v.CompanyId)
  218. mobiles = append(mobiles, v.Mobile)
  219. }
  220. sellNameMap := services.GetSellNameMapByCompanyIds(sellerCompanyIds)
  221. mapIndustrialLabel := GetArticleIndustrialLabelByArticleId(articleIds) // 关联产业
  222. mapSubjectLabel := GetArticleSubjectLabelByArticleId(articleIds) // 关联标的
  223. //根据手机号获取这些用户的信息
  224. listUser, e := models.GetWxUserByOutboundMobiles(mobiles)
  225. if e != nil {
  226. err = errors.New("GetWxUserOutboundMobiles, Err: " + e.Error())
  227. return
  228. }
  229. mapUserRealname := make(map[string]string)
  230. for _, v := range listUser {
  231. mapUserRealname[v.Mobile] = v.RealName
  232. }
  233. var condition string
  234. var pars []interface{}
  235. //获取文章map
  236. mapArticle := make(map[int]*cygx.CygxReportArticle)
  237. lenarticleIds := len(articleIds)
  238. if lenarticleIds > 0 {
  239. condition = " AND art.article_id IN (" + utils.GetOrmInReplace(lenarticleIds) + ") GROUP BY art.article_id "
  240. pars = append(pars, articleIds)
  241. list, e := cygx.GetReportArticleList(condition, pars, 0, lenarticleIds, 1)
  242. if e != nil && e.Error() != utils.ErrNoRow() {
  243. err = e
  244. return
  245. }
  246. if len(list) > 0 {
  247. for _, v := range list {
  248. mapArticle[v.ArticleId] = v
  249. }
  250. }
  251. }
  252. //获取研选专栏map
  253. mapYanxuanSpecial := make(map[int]*cygx.CygxYanxuanSpeciaResplItem)
  254. lenyanxuanSpecialIds := len(yanxuanSpecialIds)
  255. if lenyanxuanSpecialIds > 0 {
  256. pars = make([]interface{}, 0)
  257. condition = " AND a.id IN (" + utils.GetOrmInReplace(lenyanxuanSpecialIds) + ")"
  258. pars = append(pars, yanxuanSpecialIds)
  259. list, e := cygx.GetYanxuanSpecialListByCondition(condition, pars, 0, lenyanxuanSpecialIds)
  260. if e != nil && e.Error() != utils.ErrNoRow() {
  261. err = e
  262. return
  263. }
  264. if len(list) > 0 {
  265. for _, v := range list {
  266. mapYanxuanSpecial[v.Id] = v
  267. }
  268. }
  269. }
  270. for _, v := range items {
  271. item := new(cygx.UserInteraction)
  272. if v.Source == utils.CYGX_OBJ_ARTICLE {
  273. item.IndustryName = strings.Join(mapIndustrialLabel[v.SourceId], ",")
  274. item.SubjectNameStr = strings.Join(mapSubjectLabel[v.SourceId], ",")
  275. if v.SourceId >= utils.SummaryArticleId {
  276. item.ArticleType = 1
  277. } else {
  278. item.ArticleType = 2
  279. }
  280. //如果对应的map不为空,就赋值
  281. if mapArticle[v.SourceId] != nil {
  282. item.Title = mapArticle[v.SourceId].Title
  283. item.PublishDate = mapArticle[v.SourceId].PublishDate
  284. item.PermissionName = mapArticle[v.SourceId].PermissionName
  285. item.ArticleIdMd5 = mapArticle[v.SourceId].ArticleIdMd5
  286. item.ReportId = mapArticle[v.SourceId].ReportId
  287. }
  288. }
  289. if v.Source == utils.CYGX_OBJ_YANXUANSPECIAL {
  290. item.PermissionName = utils.CHART_PERMISSION_NAME_MF_YANXUAN
  291. //如果对应的map不为空,就赋值
  292. if mapYanxuanSpecial[v.SourceId] != nil {
  293. item.Title = mapYanxuanSpecial[v.SourceId].Title
  294. item.PublishDate = mapYanxuanSpecial[v.SourceId].PublishTime
  295. item.SpecialType = mapYanxuanSpecial[v.SourceId].Type
  296. }
  297. }
  298. item.ArticleId = v.SourceId
  299. item.CreateTime = v.CreateTime
  300. item.UserId = v.UserId
  301. item.RealName = v.RealName
  302. if item.RealName == "" {
  303. item.RealName = mapUserRealname[v.Mobile]
  304. }
  305. item.Mobile = v.Mobile
  306. item.CompanyId = v.CompanyId
  307. item.CompanyName = v.CompanyName
  308. item.SellerName = sellNameMap[v.CompanyId]
  309. item.RegisterPlatform = v.RegisterPlatform
  310. item.RegisterPlatformText = GetArticleSourcePlatformText(v.RegisterPlatform)
  311. item.StopTime = strconv.Itoa(v.StopTime)
  312. itemsResp = append(itemsResp, item)
  313. }
  314. }
  315. return
  316. }
  317. // 处理文章、研选专栏的查询信息回显
  318. func HandleArticleAndYanxuanRecordList2(items []*cygx.UserInteraction) (itemsResp []*cygx.UserInteraction, err error) {
  319. itemsResp = make([]*cygx.UserInteraction, 0)
  320. if len(items) > 0 {
  321. var articleIds []int // 文章ID
  322. var yanxuanSpecialIds []int // 研选专栏ID
  323. var sellerCompanyIds []int // 公司ID
  324. var mobiles []string // 手机号
  325. for _, v := range items {
  326. articleIds = append(articleIds, v.ArticleId)
  327. sellerCompanyIds = append(sellerCompanyIds, v.CompanyId)
  328. mobiles = append(mobiles, v.Mobile)
  329. }
  330. sellNameMap := services.GetSellNameMapByCompanyIds(sellerCompanyIds)
  331. mapIndustrialLabel := GetArticleIndustrialLabelByArticleId(articleIds) // 关联产业
  332. mapSubjectLabel := GetArticleSubjectLabelByArticleId(articleIds) // 关联标的
  333. //根据手机号获取这些用户的信息
  334. listUser, e := models.GetWxUserByOutboundMobiles(mobiles)
  335. if e != nil {
  336. err = errors.New("GetWxUserOutboundMobiles, Err: " + e.Error())
  337. return
  338. }
  339. mapUserRealname := make(map[string]string)
  340. for _, v := range listUser {
  341. mapUserRealname[v.Mobile] = v.RealName
  342. }
  343. var condition string
  344. var pars []interface{}
  345. //获取文章map
  346. mapArticle := make(map[int]*cygx.CygxReportArticle)
  347. lenarticleIds := len(articleIds)
  348. if lenarticleIds > 0 {
  349. condition = " AND art.article_id IN (" + utils.GetOrmInReplace(lenarticleIds) + ") GROUP BY art.article_id "
  350. pars = append(pars, articleIds)
  351. list, e := cygx.GetReportArticleList(condition, pars, 0, lenarticleIds, 1)
  352. if e != nil && e.Error() != utils.ErrNoRow() {
  353. err = e
  354. return
  355. }
  356. if len(list) > 0 {
  357. for _, v := range list {
  358. mapArticle[v.ArticleId] = v
  359. }
  360. }
  361. }
  362. //获取研选专栏map
  363. mapYanxuanSpecial := make(map[int]*cygx.CygxYanxuanSpeciaResplItem)
  364. lenyanxuanSpecialIds := len(yanxuanSpecialIds)
  365. if lenyanxuanSpecialIds > 0 {
  366. pars = make([]interface{}, 0)
  367. condition = " AND a.id IN (" + utils.GetOrmInReplace(lenyanxuanSpecialIds) + ")"
  368. pars = append(pars, yanxuanSpecialIds)
  369. list, e := cygx.GetYanxuanSpecialListByCondition(condition, pars, 0, lenyanxuanSpecialIds)
  370. if e != nil && e.Error() != utils.ErrNoRow() {
  371. err = e
  372. return
  373. }
  374. if len(list) > 0 {
  375. for _, v := range list {
  376. mapYanxuanSpecial[v.Id] = v
  377. }
  378. }
  379. }
  380. for _, v := range items {
  381. item := new(cygx.UserInteraction)
  382. item.IndustryName = strings.Join(mapIndustrialLabel[v.ArticleId], ",")
  383. item.SubjectNameStr = strings.Join(mapSubjectLabel[v.ArticleId], ",")
  384. if v.ArticleId >= utils.SummaryArticleId {
  385. item.ArticleType = 1
  386. } else {
  387. item.ArticleType = 2
  388. }
  389. //如果对应的map不为空,就赋值
  390. if mapArticle[v.ArticleId] != nil {
  391. item.Title = mapArticle[v.ArticleId].Title
  392. item.PublishDate = mapArticle[v.ArticleId].PublishDate
  393. item.PermissionName = mapArticle[v.ArticleId].PermissionName
  394. item.ArticleIdMd5 = mapArticle[v.ArticleId].ArticleIdMd5
  395. item.ReportId = mapArticle[v.ArticleId].ReportId
  396. }
  397. item.ArticleId = v.ArticleId
  398. item.CreateTime = v.CreateTime
  399. item.UserId = v.UserId
  400. item.RealName = v.RealName
  401. if item.RealName == "" {
  402. item.RealName = mapUserRealname[v.Mobile]
  403. }
  404. item.Mobile = v.Mobile
  405. item.CompanyId = v.CompanyId
  406. item.CompanyName = v.CompanyName
  407. item.SellerName = sellNameMap[v.CompanyId]
  408. item.RegisterPlatform = v.RegisterPlatform
  409. item.RegisterPlatformText = GetArticleSourcePlatformText(v.RegisterPlatform)
  410. item.StopTime = v.StopTime
  411. itemsResp = append(itemsResp, item)
  412. }
  413. }
  414. return
  415. }
  416. //
  417. //func init() {
  418. // SendWxMsgWithroadshowEssence(1000546)
  419. //}
  420. // 路演精华的文章做模板消息推送
  421. func SendWxMsgWithroadshowEssence(articleId int) (err error) {
  422. defer func() {
  423. if err != nil {
  424. fmt.Println(err)
  425. go alarm_msg.SendAlarmMsg("路演精华的文章做模板消息推送送,发送模版消息失败,Err:"+err.Error(), 3)
  426. utils.FileLog.Info(fmt.Sprintf("路演精华的文章做模板消息推送失败,Err:%s,%s", err.Error()))
  427. }
  428. }()
  429. detail, e := cygx.GetArticleRoadshowEssenceDetail(articleId)
  430. if e != nil {
  431. err = errors.New("获取详情失败" + e.Error())
  432. return
  433. }
  434. if detail == nil {
  435. err = errors.New("获取详情失败")
  436. return
  437. }
  438. //fmt.Println(detail)
  439. permissionStr, e := company.GetPermissionIdById(strconv.Itoa(detail.ChartPermissionId))
  440. if e != nil {
  441. err = errors.New("获取主客观权限失败" + e.Error())
  442. return
  443. }
  444. // 获取所有有权的用户的 openid
  445. openidPowerList, e := cygx.GetCygxUserRecordPowerArticle(permissionStr)
  446. if e != nil {
  447. err = errors.New("获取所有有权的用户的 openid失败" + e.Error())
  448. return
  449. }
  450. //获取关注对应产业的用户信息
  451. industryFllowList, e := cygx.GetCygxUserFllowOpenid(articleId)
  452. if e != nil {
  453. err = errors.New("获取关注对应产业的用户信息失败 " + e.Error())
  454. return
  455. }
  456. mapOpenidFllow := make(map[int]string)
  457. for _, v := range industryFllowList {
  458. mapOpenidFllow[v.UserId] = v.OpenId
  459. }
  460. //获取拒绝接收推送的的用户的 openid
  461. mapOpenidRefuset := make(map[int]string)
  462. openidRefusetList, e := cygx.GetCygxUserRefusetOpenid()
  463. if e != nil && e.Error() != utils.ErrNoRow() {
  464. err = errors.New("获取拒绝接收推送的的用户的 openid 失败" + e.Error())
  465. return
  466. }
  467. for _, v := range openidRefusetList {
  468. mapOpenidRefuset[v.UserId] = v.OpenId
  469. }
  470. //获取提交过推送规则的用户的 openid
  471. mapUserIdChooseSend := make(map[int]int)
  472. chooseSendtList, err := cygx.GetCygxXzsChooseSend("")
  473. if err != nil && err.Error() != utils.ErrNoRow() {
  474. return err
  475. }
  476. for _, v := range chooseSendtList {
  477. mapUserIdChooseSend[v.UserId] = v.UserId
  478. }
  479. openIdArr := make([]string, len(openidPowerList))
  480. for i, v := range openidPowerList {
  481. if _, ok := mapOpenidRefuset[v.UserId]; ok {
  482. continue //如果用户选择了拒绝推送消息,那么就不做模板消息推送
  483. }
  484. if _, ok := mapUserIdChooseSend[v.UserId]; ok {
  485. if _, ok := mapOpenidFllow[v.UserId]; !ok {
  486. continue //如果用户提交过关注信息,而且这个产业他没有关注,那么不做推送
  487. }
  488. }
  489. openIdArr[i] = v.OpenId
  490. }
  491. fmt.Println(openIdArr)
  492. first := "【路演精华】已发布,欢迎查看"
  493. keyword1 := detail.Title
  494. keyword2 := "已发布"
  495. keyword3 := detail.PublishDate
  496. keyword4 := detail.Abstract
  497. remark := "点击查看详情"
  498. redirectUrl := utils.WX_MSG_PATH_ROAD_ESSENCE + strconv.Itoa(detail.ArticleId) + "&IsSendWx=1"
  499. sendInfo := new(services.SendWxTemplate)
  500. sendInfo.First = first
  501. sendInfo.Keyword1 = keyword1
  502. sendInfo.Keyword2 = keyword2
  503. sendInfo.Keyword3 = keyword3
  504. sendInfo.Keyword4 = keyword4
  505. sendInfo.Remark = remark
  506. sendInfo.TemplateId = utils.WxMsgTemplateIdActivityChangeApplyXzs
  507. sendInfo.RedirectUrl = redirectUrl
  508. sendInfo.RedirectTarget = 3
  509. sendInfo.Resource = strconv.Itoa(detail.ArticleId)
  510. sendInfo.SendType = utils.TEMPLATE_MSG_CYGX_ROADSHOW_VIDEO
  511. sendInfo.OpenIdArr = openIdArr
  512. e = services.SendTemplateMsg(sendInfo)
  513. if e != nil {
  514. err = errors.New("推送模板消息失败" + e.Error())
  515. return
  516. }
  517. return
  518. }