activity.go 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072
  1. package services
  2. import (
  3. "context"
  4. "fmt"
  5. "github.com/tealeg/xlsx"
  6. "hongze/hongze_cygx/models"
  7. "hongze/hongze_cygx/utils"
  8. "os"
  9. "path/filepath"
  10. "strconv"
  11. "strings"
  12. "time"
  13. )
  14. //修改活动状态
  15. func UpdateActivitySattus(cont context.Context) (err error) {
  16. //defer func() {
  17. // if err != nil {
  18. // fmt.Println("同步失败,Err:", err.Error())
  19. // }
  20. //}()
  21. go models.UpdateActivitySattusToHaveInHand()
  22. go models.UpdateActivitySattusToComplete()
  23. return
  24. }
  25. //推送会议开始消息提醒60分钟前
  26. func SendActivityBeginMsg(cont context.Context) (err error) {
  27. defer func() {
  28. if err != nil {
  29. go utils.SendAlarmMsg("60分钟会议消息提醒失败", 2)
  30. fmt.Println("发送失败,Err:", err.Error())
  31. }
  32. }()
  33. endDate := time.Now().Add(+time.Minute * 60).Format(utils.FormatDateTime)
  34. listActivity, err := models.GetActivitySendMsgListAll(endDate)
  35. fmt.Println(len(listActivity))
  36. if err != nil {
  37. fmt.Println("GetActivitySendMsgListAll Err:", err.Error())
  38. return
  39. }
  40. if len(listActivity) == 0 {
  41. return
  42. }
  43. var remark = "点击查看活动详情"
  44. var signupIds string
  45. for _, v := range listActivity {
  46. signupIds += strconv.Itoa(v.Id) + ","
  47. var reserveResults string
  48. var first string
  49. openIdItem := new(models.OpenIdList)
  50. openIdItem.OpenId = v.OpenId
  51. openIdList := make([]*models.OpenIdList, 0)
  52. openIdList = append(openIdList, openIdItem)
  53. //if v.FailType == 0 {
  54. // reserveResults = "成功"
  55. //} else if v.FailType == 1 {
  56. // reserveResults = "失败(总人数已满)"
  57. //} else if v.FailType == 2 {
  58. // reserveResults = "失败(单机构超限制)"
  59. //} else if v.FailType == 3 {
  60. // reserveResults = "失败(爽约次数超限)"
  61. //}
  62. reserveResults = "--"
  63. first = "您有一场【" + v.ActivityTypeName + "】将在1小时后开始"
  64. SendWxMsgWithFrequency(first, v.ActivityName, reserveResults, v.ActivityTime, v.Address, remark, openIdList, v.ActivityId)
  65. }
  66. if len(signupIds) == 0 {
  67. return
  68. }
  69. signupIds = strings.TrimRight(signupIds, ",")
  70. err = models.UPdateSendedMsgStatus(signupIds)
  71. if err != nil {
  72. var msg string
  73. go utils.SendEmail("发送模版消息失败"+"【"+utils.APPNAME+"】"+time.Now().Format(utils.FormatDateTime), msg+";Err:"+err.Error(), utils.EmailSendToUsers)
  74. utils.FileLog.Info("发送模版消息失败,Err:%s", err.Error())
  75. }
  76. return
  77. }
  78. //推送会议开始消息提醒15分钟前
  79. func SendActivityBeginMsgMeeting(cont context.Context) (err error) {
  80. defer func() {
  81. if err != nil {
  82. go utils.SendAlarmMsg("15分钟会议消息提醒失败", 2)
  83. fmt.Println("发送失败,Err:", err.Error())
  84. }
  85. }()
  86. endDate := time.Now().Add(+time.Minute * 15).Format(utils.FormatDateTime)
  87. listActivity, err := models.GetActivitySendMsgListAllMeeting(endDate)
  88. if err != nil {
  89. fmt.Println("GetActivitySendMsgListAll Err:", err.Error())
  90. return
  91. }
  92. if len(listActivity) == 0 {
  93. return
  94. }
  95. var signupIds string
  96. var remark = "点击查看活动详情"
  97. for _, v := range listActivity {
  98. signupIds += strconv.Itoa(v.Id) + ","
  99. var reserveResults string
  100. var first string
  101. openIdItem := new(models.OpenIdList)
  102. openIdItem.OpenId = v.OpenId
  103. openIdList := make([]*models.OpenIdList, 0)
  104. openIdList = append(openIdList, openIdItem)
  105. reserveResults = "--"
  106. first = "您有一场【" + v.ActivityTypeName + "】将在15分钟后开始"
  107. SendWxMsgWithFrequency(first, v.ActivityName, reserveResults, v.ActivityTime, "--", remark, openIdList, v.ActivityId)
  108. }
  109. if len(signupIds) == 0 {
  110. return
  111. }
  112. signupIds = strings.TrimRight(signupIds, ",")
  113. err = models.UPdateSendedMsgMeetingStatus(signupIds)
  114. if err != nil {
  115. var msg string
  116. go utils.SendEmail("发送模版消息失败"+"【"+utils.APPNAME+"】"+time.Now().Format(utils.FormatDateTime), msg+";Err:"+err.Error(), utils.EmailSendToUsers)
  117. utils.FileLog.Info("发送模版消息失败,Err:%s", err.Error())
  118. }
  119. return
  120. }
  121. //预约外呼名单,会前1小时自动发送邮件给专家组
  122. func SendEmailFileToExpert(cont context.Context) (err error) {
  123. var msg string
  124. var touser string
  125. defer func() {
  126. if err != nil {
  127. fmt.Println("err:", err)
  128. go utils.SendAlarmMsg("发送附件模版消息失败", 2)
  129. go utils.SendEmail("发送附件模版消息失败"+"【"+utils.APPNAME+"】"+time.Now().Format(utils.FormatDateTime), msg+";Err:"+err.Error(), utils.EmailSendToUsers)
  130. utils.FileLog.Info("发送附件模版消息失败,Err:%s", err.Error())
  131. }
  132. if msg != "" {
  133. fmt.Println(msg)
  134. utils.FileLog.Info("发送模版消息失败,msg:%s", msg)
  135. }
  136. }()
  137. endDate := time.Now().Add(+time.Minute * 30).Format(utils.FormatDateTime)
  138. total, err := models.GetCountActivityIdToSendFile(endDate)
  139. if total == 0 {
  140. fmt.Println("发送附件完成0")
  141. return nil
  142. }
  143. if err != nil {
  144. msg = "发送附件模版消息失败 Err:" + err.Error()
  145. return
  146. }
  147. listActivity, err := models.GetActivityIdToSendFile(endDate)
  148. if err != nil {
  149. msg = "发送附件模版消息失败 Err:" + err.Error()
  150. return
  151. }
  152. for _, v := range listActivity {
  153. activityInfo, _ := models.GetAddActivityInfoById(v.ActivityId)
  154. if activityInfo == nil {
  155. msg = "活动不存在,Err:activityId:" + strconv.Itoa(v.ActivityId)
  156. return
  157. }
  158. list, errFile := models.GetSignupExport(v.ActivityId)
  159. if errFile != nil {
  160. msg = "获取失败,Err:" + errFile.Error()
  161. return
  162. }
  163. //创建excel
  164. dir, errFile := os.Executable()
  165. exPath := filepath.Dir(dir)
  166. downLoadnFilePath := exPath + "/" + time.Now().Format(utils.FormatDateTimeUnSpace) + utils.GetRandDigit(5) + ".xlsx"
  167. xlsxFile := xlsx.NewFile()
  168. if errFile != nil {
  169. msg = "生成文件失败Err:" + errFile.Error()
  170. return
  171. }
  172. style := xlsx.NewStyle()
  173. alignment := xlsx.Alignment{
  174. Horizontal: "center",
  175. Vertical: "center",
  176. WrapText: true,
  177. }
  178. style.Alignment = alignment
  179. style.ApplyAlignment = true
  180. sheet, errFile := xlsxFile.AddSheet("外呼名单")
  181. if errFile != nil {
  182. msg = "新增Sheet失败,Err:" + errFile.Error()
  183. return
  184. }
  185. //设置宽度
  186. _ = sheet.SetColWidth(1, 1, 15)
  187. _ = sheet.SetColWidth(3, 3, 30)
  188. //标头
  189. rowTitle := sheet.AddRow()
  190. cellA := rowTitle.AddCell()
  191. cellA.Value = "姓名"
  192. cellB := rowTitle.AddCell()
  193. cellB.Value = "外呼号码"
  194. cellC := rowTitle.AddCell()
  195. cellC.Value = "国际代码"
  196. cellD := rowTitle.AddCell()
  197. cellD.Value = "公司名称"
  198. cellE := rowTitle.AddCell()
  199. cellE.Value = "所属销售"
  200. for _, item := range list {
  201. row := sheet.AddRow()
  202. cellA := row.AddCell()
  203. cellA.Value = item.RealName
  204. cellB := row.AddCell()
  205. cellB.Value = item.OutboundMobile
  206. cellC := row.AddCell()
  207. if item.CountryCode == "" {
  208. cellC.Value = "86"
  209. } else {
  210. cellC.Value = item.CountryCode
  211. }
  212. cellD := row.AddCell()
  213. cellD.Value = item.CompanyName
  214. cellE := row.AddCell()
  215. cellE.Value = item.SellerName
  216. }
  217. errFile = xlsxFile.Save(downLoadnFilePath)
  218. if errFile != nil {
  219. msg = "保存文件失败Err:" + errFile.Error()
  220. return
  221. }
  222. title := activityInfo.ActivityName + "外呼名单"
  223. content := "外呼名单详情"
  224. fileName := downLoadnFilePath
  225. if activityInfo.ChartPermissionName == "科技" {
  226. touser = utils.EmailTechnology
  227. } else if activityInfo.ChartPermissionName == "医药" {
  228. touser = utils.EmailMedicine
  229. } else if activityInfo.ChartPermissionName == "消费" {
  230. touser = utils.EmailConsumption
  231. } else if activityInfo.ChartPermissionName == "智造" {
  232. touser = utils.EmailZhizao
  233. } else if activityInfo.ChartPermissionName == "策略" {
  234. touser = utils.EmailStrategy
  235. } else if activityInfo.ChartPermissionName == "研选" {
  236. touser = utils.EmailExpert
  237. }
  238. sendResult := utils.SendEmailByHongze(title, content, touser, fileName, title+".xlsx")
  239. if sendResult {
  240. errFile = models.UPdateActivityIdToSendFile(v.ActivityId)
  241. if errFile != nil {
  242. msg = "获取失败,Err:" + errFile.Error()
  243. return
  244. }
  245. os.Remove(downLoadnFilePath)
  246. } else {
  247. go utils.SendEmail("发送附件模版消息失败"+"【"+utils.APPNAME+"】"+time.Now().Format(utils.FormatDateTime), msg+";Err:"+activityInfo.ActivityName, utils.EmailSendToUsers)
  248. utils.FileLog.Info("发送附件模版消息失败,Err:%s", activityInfo.ActivityName)
  249. }
  250. }
  251. return
  252. }
  253. func EditOutboundMobile(cont context.Context) (err error) {
  254. defer func() {
  255. if err != nil {
  256. fmt.Println("发送失败,Err:", err.Error())
  257. }
  258. }()
  259. list, err := models.GetActivitySignupListAll()
  260. if err != nil {
  261. fmt.Println("GetActivitySendMsgListAll Err:", err.Error())
  262. return
  263. }
  264. for _, v := range list {
  265. err = models.UPdateSignup(v)
  266. fmt.Println("修改:", strconv.Itoa(v.Id))
  267. if err != nil {
  268. fmt.Println("发送失败,Err:", err.Error()+strconv.Itoa(v.Id))
  269. }
  270. }
  271. fmt.Println("修改完成")
  272. return
  273. }
  274. //同步用户绑定手机号以及区号
  275. func EditUserOutboundMobile(cont context.Context) (err error) {
  276. defer func() {
  277. if err != nil {
  278. fmt.Println("发送失败,Err:", err.Error())
  279. }
  280. }()
  281. list, err := models.GetUserListAll()
  282. if err != nil {
  283. fmt.Println("GetActivitySendMsgListAll Err:", err.Error())
  284. return
  285. }
  286. for _, v := range list {
  287. err = models.UPdateUserCountryCode(v)
  288. fmt.Println("修改:", strconv.Itoa(v.UserId))
  289. if err != nil {
  290. fmt.Println("发送失败,Err:", err.Error()+strconv.Itoa(v.UserId))
  291. }
  292. }
  293. fmt.Println("修改完成")
  294. return
  295. }
  296. //获取 用户类型 //1、永续客户 //2、大套餐客户(4个行业全开通的正式客户) //3、分行业套餐客户(开通对应行业的正式客户) //4、仅开通专家套餐的正式客户 //5、开通对应行业套餐或专家套餐的试用客户
  297. func GetUserType(companyId int) (userType int, permissionStrnew string, err error) {
  298. var permissionStr, permissionZhegnshiStr string
  299. if companyId <= 1 {
  300. userType = 0
  301. } else {
  302. total, errs := models.GetCountCompanyDetailByIdGroup(companyId)
  303. if errs != nil {
  304. err = errs
  305. return
  306. }
  307. if total == 0 {
  308. userType = 0
  309. } else {
  310. companyDetail, errs := models.GetCompanyDetailByIdGroup(companyId)
  311. if errs != nil {
  312. err = errs
  313. return
  314. }
  315. permissionStr, errs = models.GetCompanyPermissionByUser(companyId)
  316. if errs != nil {
  317. err = errs
  318. return
  319. }
  320. permissionZhegnshiStr, errs = models.GetCompanyPermissionByUserZhengShi(companyId)
  321. if errs != nil {
  322. err = errs
  323. return
  324. }
  325. //1、永续客户 //2、大套餐客户(4个行业全开通的正式客户) //3、分行业套餐客户(开通对应行业的正式客户) //4、仅开通专家套餐的正式客户 //5、开通对应行业套餐或专家套餐的试用客户
  326. if companyDetail.Status == "永续" {
  327. userType = 1
  328. } else if companyDetail.Status == "试用" {
  329. userType = 5
  330. } else if companyDetail.Status == "正式" {
  331. if permissionStr == "专家" {
  332. userType = 4
  333. } else if strings.Count(permissionZhegnshiStr, "医药") == 2 && strings.Count(permissionZhegnshiStr, "消费") == 2 && strings.Count(permissionZhegnshiStr, "科技") == 2 && strings.Count(permissionZhegnshiStr, "智造") == 2 {
  334. userType = 2
  335. } else {
  336. userType = 3
  337. }
  338. if userType == 3 {
  339. if !strings.Contains(permissionStr, "医药") && !strings.Contains(permissionStr, "消费") && !strings.Contains(permissionStr, "科技") && !strings.Contains(permissionStr, "智造") {
  340. userType = 4
  341. }
  342. }
  343. }
  344. }
  345. }
  346. permissionStrnew = permissionStr
  347. return
  348. }
  349. // 校验被分享的用户是否有查看详情的权限
  350. func GetShareNoPowe(activityInfo *models.ActivityDetail, permissionStr string, userType int) (noPower bool, err error) {
  351. //var noPower bool
  352. if (userType == 1 || userType == 4 || userType == 5) && !strings.Contains(activityInfo.CustomerTypeIds, strconv.Itoa(userType)) {
  353. noPower = true
  354. }
  355. //1、永续客户 //2、大套餐客户(4个行业全开通的正式客户) //3、分行业套餐客户(开通对应行业的正式客户) //4、仅开通专家套餐的正式客户 //5、开通对应行业套餐或专家套餐的试用客户
  356. if userType == 2 && strings.Contains(permissionStr, "专家") && !strings.Contains(activityInfo.CustomerTypeIds, strconv.Itoa(2)) && !strings.Contains(activityInfo.CustomerTypeIds, strconv.Itoa(3)) && !strings.Contains(activityInfo.CustomerTypeIds, strconv.Itoa(4)) {
  357. noPower = true
  358. }
  359. if userType == 2 && !strings.Contains(permissionStr, "专家") && !strings.Contains(activityInfo.CustomerTypeIds, strconv.Itoa(2)) && !strings.Contains(activityInfo.CustomerTypeIds, strconv.Itoa(3)) {
  360. noPower = true
  361. }
  362. if userType == 3 && strings.Contains(permissionStr, "专家") && !strings.Contains(activityInfo.CustomerTypeIds, strconv.Itoa(3)) && !strings.Contains(activityInfo.CustomerTypeIds, strconv.Itoa(4)) {
  363. noPower = true
  364. }
  365. if userType == 3 && !strings.Contains(permissionStr, "专家") && !strings.Contains(activityInfo.CustomerTypeIds, strconv.Itoa(3)) {
  366. noPower = true
  367. }
  368. return
  369. }
  370. // 校验用户报名的权限
  371. func GetHavePower(activityInfo *models.ActivityDetail, permissionStr, companyDetailStatus string, userType int) (havePower bool, err error) {
  372. if (activityInfo.ActivityTypeId == 1 || activityInfo.ActivityTypeId == 3) && strings.Contains(permissionStr, "专家") && activityInfo.LimitPeopleNum == 0 {
  373. havePower = true
  374. } else if activityInfo.ActivityTypeId == 3 && strings.Contains(permissionStr, "专家") && companyDetailStatus == "正式" && strings.Contains(activityInfo.CustomerTypeIds, "4") {
  375. havePower = true
  376. } else if activityInfo.ActivityTypeId == 3 && strings.Contains(permissionStr, "专家") && companyDetailStatus == "试用" && strings.Contains(activityInfo.CustomerTypeIds, "5") {
  377. havePower = true
  378. //} else if strings.Contains(permissionStr, activityInfo.ChartPermissionName) && strings.Contains(activityInfo.CustomerTypeIds, strconv.Itoa(userType)) {
  379. // havePower = true
  380. //} else if strings.Contains(permissionStr, activityInfo.ChartPermissionName) {
  381. // havePower = true
  382. } else if (activityInfo.ActivityTypeId == 1 || activityInfo.ActivityTypeId == 3 || activityInfo.ActivityTypeId == 4 || activityInfo.ActivityTypeId == 5) && strings.Contains(permissionStr, "专家") {
  383. havePower = true
  384. }
  385. if activityInfo.ActivityTypeId == 2 || activityInfo.ActivityTypeId == 6 {
  386. if strings.Contains(permissionStr, activityInfo.ChartPermissionName+"(主观)") {
  387. havePower = true
  388. }
  389. } else {
  390. if strings.Contains(permissionStr, activityInfo.ChartPermissionName+"(客观)") {
  391. havePower = true
  392. }
  393. }
  394. if (activityInfo.ChartPermissionName == "研选" || activityInfo.ChartPermissionName == "策略") && strings.Contains(permissionStr, activityInfo.ChartPermissionName) {
  395. havePower = true
  396. }
  397. return
  398. }
  399. //研选系列专家电话会,会前1小时将问题列表发送给邮箱
  400. func SendEmailFileForAskMsgResearch(cont context.Context) (err error) {
  401. var msg string
  402. //var touser string
  403. defer func() {
  404. if err != nil {
  405. go utils.SendAlarmMsg("发送附件模版消息失败", 2)
  406. go utils.SendEmail("发送附件模版消息失败"+"【"+utils.APPNAME+"】"+time.Now().Format(utils.FormatDateTime), msg+";Err:"+err.Error(), utils.EmailSendToUsers)
  407. }
  408. if msg != "" {
  409. go utils.SendAlarmMsg(msg, 2)
  410. utils.FileLog.Info("发送模版消息失败,msg:%s", msg)
  411. }
  412. }()
  413. endDate := time.Now().Add(+time.Minute * 60).Format(utils.FormatDateTime)
  414. condition := `AND a.activity_type_id = 1 AND a.chart_permission_name = '研选' `
  415. total, err := models.GetCountActivityResearchToSendFile(condition, endDate)
  416. if total == 0 {
  417. fmt.Println("发送附件完成0")
  418. return nil
  419. }
  420. if err != nil {
  421. msg = "发送附件模版消息失败 Err:" + err.Error()
  422. return
  423. }
  424. listActivity, err := models.GetActivityResearchToSendFile(condition, endDate)
  425. if err != nil {
  426. msg = "发送附件模版消息失败 Err:" + err.Error()
  427. return
  428. }
  429. for _, v := range listActivity {
  430. activityInfo, _ := models.GetAddActivityInfoById(v.ActivityId)
  431. if activityInfo == nil {
  432. msg = "活动不存在,Err:activityId:" + strconv.Itoa(v.ActivityId)
  433. return
  434. }
  435. list, errFile := models.GetActivityMsgExport(v.ActivityId)
  436. if errFile != nil {
  437. msg = "获取失败,Err:" + errFile.Error()
  438. return
  439. }
  440. for _, v2 := range list {
  441. user, err := models.GetWxUserItemByUserId(v2.UserId)
  442. if err != nil && err.Error() != utils.ErrNoRow() {
  443. return err
  444. }
  445. //获取销售信息
  446. sellerItem, err := models.GetSellerByCompanyIdCheckFicc(v2.CompanyId, 2)
  447. if err != nil && err.Error() != utils.ErrNoRow() {
  448. return err
  449. }
  450. //给研究员推送消息
  451. if sellerItem != nil {
  452. openIpItem, _ := models.GetUserRecordByMobile(4, utils.ActSendMsgMobile)
  453. if openIpItem != nil && openIpItem.OpenId != "" {
  454. SendActivityAskApplyTemplateMsg(user.RealName+"——"+user.CompanyName+"(所属销售:"+sellerItem.RealName+")", v2.CreateTime, v2.Content, activityInfo.ActivityName, openIpItem.OpenId, activityInfo.ActivityId)
  455. }
  456. }
  457. //给所属销售推送消息
  458. if sellerItem != nil {
  459. openIpItem, _ := models.GetUserRecordByMobile(4, sellerItem.Mobile)
  460. if openIpItem != nil && openIpItem.OpenId != "" {
  461. SendActivityAskApplyTemplateMsg(user.RealName+"——"+user.CompanyName+"(所属销售:"+sellerItem.RealName+")", v2.CreateTime, v2.Content, activityInfo.ActivityName, openIpItem.OpenId, activityInfo.ActivityId)
  462. }
  463. }
  464. }
  465. errFile = models.UPdateActivityMsgToSendFile(v.ActivityId)
  466. if errFile != nil {
  467. msg = "获取失败,Err:" + errFile.Error()
  468. return
  469. }
  470. }
  471. return
  472. }
  473. //非研选系列专家电话会,根据主持人姓名,会前15分钟将问题列表发送给至该主持人对应邮箱
  474. func SendEmailFileForAskMsg(cont context.Context) (err error) {
  475. var msg string
  476. //var touser string
  477. defer func() {
  478. if err != nil {
  479. go utils.SendAlarmMsg("发送附件模版消息失败", 2)
  480. go utils.SendEmail("发送附件模版消息失败"+"【"+utils.APPNAME+"】"+time.Now().Format(utils.FormatDateTime), msg+";Err:"+err.Error(), utils.EmailSendToUsers)
  481. }
  482. if msg != "" {
  483. go utils.SendAlarmMsg(msg, 2)
  484. utils.FileLog.Info("发送模版消息失败,msg:%s", msg)
  485. }
  486. }()
  487. endDate := time.Now().Add(+time.Minute * 15).Format(utils.FormatDateTime)
  488. condition := `AND a.activity_type_id = 1 AND a.chart_permission_name != '研选' `
  489. total, err := models.GetCountActivityResearchToSendFile(condition, endDate)
  490. if total == 0 {
  491. fmt.Println("发送附件完成0")
  492. return nil
  493. }
  494. if err != nil {
  495. msg = "发送附件模版消息失败 Err:" + err.Error()
  496. return
  497. }
  498. listActivity, err := models.GetActivityResearchToSendFile(condition, endDate)
  499. if err != nil {
  500. msg = "发送附件模版消息失败 Err:" + err.Error()
  501. return
  502. }
  503. listEmail, errEmail := models.GetAskEmail()
  504. if errEmail != nil {
  505. msg = "获取失败,Err:" + errEmail.Error()
  506. return
  507. }
  508. for _, v := range listActivity {
  509. activityInfo, _ := models.GetAddActivityInfoById(v.ActivityId)
  510. if activityInfo == nil {
  511. msg = "活动不存在,Err:activityId:" + strconv.Itoa(v.ActivityId)
  512. return
  513. }
  514. list, errFile := models.GetActivityMsgExport(v.ActivityId)
  515. if errFile != nil {
  516. msg = "获取失败,Err:" + errFile.Error()
  517. return
  518. }
  519. for _, v2 := range list {
  520. user, err := models.GetWxUserItemByUserId(v2.UserId)
  521. if err != nil && err.Error() != utils.ErrNoRow() {
  522. return err
  523. }
  524. var sendMobile string
  525. for _, vEmail := range listEmail {
  526. if strings.Index(activityInfo.Host, vEmail.Name) > 0 {
  527. sendMobile = vEmail.Mobile
  528. }
  529. }
  530. //获取销售信息
  531. sellerItem, err := models.GetSellerByCompanyIdCheckFicc(v2.CompanyId, 2)
  532. if err != nil && err.Error() != utils.ErrNoRow() {
  533. return err
  534. }
  535. //给研究员推送模板消息
  536. if sellerItem != nil {
  537. openIpItem, _ := models.GetUserRecordByMobile(4, sendMobile)
  538. if openIpItem != nil && openIpItem.OpenId != "" {
  539. SendActivityAskApplyTemplateMsg(user.RealName+"——"+user.CompanyName+"(所属销售:"+sellerItem.RealName+")", v2.CreateTime, v2.Content, activityInfo.ActivityName, openIpItem.OpenId, activityInfo.ActivityId)
  540. }
  541. }
  542. //给销售推送模板消息
  543. if sellerItem != nil {
  544. openIpItem, _ := models.GetUserRecordByMobile(4, sellerItem.Mobile)
  545. if openIpItem != nil && openIpItem.OpenId != "" {
  546. SendActivityAskApplyTemplateMsg(user.RealName+"——"+user.CompanyName+"(所属销售:"+sellerItem.RealName+")", v2.CreateTime, v2.Content, activityInfo.ActivityName, openIpItem.OpenId, activityInfo.ActivityId)
  547. }
  548. }
  549. }
  550. errFile = models.UPdateActivityMsgToSendFile(v.ActivityId)
  551. if errFile != nil {
  552. msg = "获取失败,Err:" + errFile.Error()
  553. return
  554. }
  555. }
  556. return
  557. }
  558. //活动标签字符串处理
  559. func LabelStr(label string) (labelNew string) {
  560. slicebr := strings.Split(label, "-")
  561. if len(slicebr) < 2 {
  562. labelNew = label
  563. } else {
  564. labelNew = slicebr[1]
  565. }
  566. return labelNew
  567. }
  568. //5.3版本活动标签字符串处理
  569. func LabelStrV5(label string, isShowSubjectName int) (labelNew string) {
  570. slicebr := strings.Split(label, "-")
  571. if len(slicebr) < 2 || isShowSubjectName == 0 {
  572. labelNew = label
  573. } else {
  574. labelNew = slicebr[1]
  575. }
  576. return labelNew
  577. }
  578. func ActivityAttendanceDetail(cont context.Context) (err error) {
  579. defer func() {
  580. if err != nil {
  581. fmt.Println("ActivityAttendanceDetail Err:" + err.Error())
  582. go utils.SendAlarmMsg("同步进门财经数据失败", 2)
  583. go utils.SendEmail(utils.APPNAME+"【"+utils.RunMode+"】"+"失败提醒", "ActivityAttendanceDetail ErrMsg:"+err.Error(), utils.EmailSendToUsers)
  584. }
  585. }()
  586. var activityIds string
  587. fmt.Println("开始同步")
  588. dateTime := time.Now().AddDate(0, 0, -1).Format(utils.FormatDate)
  589. dateNow := time.Now().AddDate(0, 0, 0).Format(utils.FormatDate)
  590. startDate := dateTime + " 00:00:00"
  591. endDate := dateNow + " 23:59:59"
  592. //获取进门财经需要处理的活动
  593. listActivityRoadshow, err := models.GetRoadshowDataListByDateTime(startDate, endDate)
  594. if err != nil {
  595. fmt.Println("GetRoadshowDataListByDateTime Err:", err.Error())
  596. return err
  597. }
  598. for _, vAct := range listActivityRoadshow {
  599. doTime := utils.TimeRemoveHms2(vAct.RoadshowBeginTime)
  600. findStartDate := doTime + " 00:00:00"
  601. findEndDate := doTime + " 23:59:59"
  602. var roadshowTitle string
  603. roadshowTitle = vAct.RoadshowTitle
  604. vAct.RoadshowTitle = strings.Replace(vAct.RoadshowTitle, "【", "", -1)
  605. vAct.RoadshowTitle = strings.Replace(vAct.RoadshowTitle, "】", "", -1)
  606. vAct.RoadshowTitle = strings.Replace(vAct.RoadshowTitle, " ", "", -1)
  607. vAct.RoadshowTitle = strings.Replace(vAct.RoadshowTitle, "-", "", -1)
  608. vAct.RoadshowTitle = strings.Replace(vAct.RoadshowTitle, ":", "", -1)
  609. nameSlice := strings.Split(vAct.RoadshowTitle, "|")
  610. //fmt.Println(timeSlice[0])
  611. //对于手动匹配到的活动数据也要更新
  612. var activityName string
  613. if len(nameSlice) > 1 {
  614. //if vAct.JmcjRoadshowTitle != "" {
  615. // activityName = vAct.JmcjRoadshowTitle
  616. //} else {
  617. // activityName = nameSlice[len(nameSlice)-1]
  618. //}
  619. activityName = nameSlice[len(nameSlice)-1]
  620. if activityName != "" {
  621. //通过名称去找匹配的活动
  622. activityDetail, _ := models.GetAddActivityInfoByTitle(activityName, findStartDate, findEndDate)
  623. if activityDetail == nil {
  624. continue
  625. } else {
  626. activityIds += strconv.Itoa(activityDetail.ActivityId) + ","
  627. }
  628. list, err := models.GetRoadshowDataList(roadshowTitle, findStartDate, findEndDate)
  629. if err != nil {
  630. fmt.Println("GetTacticsList Err:", err.Error())
  631. return err
  632. }
  633. needAddAttendanc := make([]*models.CygxActivityAttendanceDetail, 0)
  634. var mobileStr string
  635. if len(list) > 0 {
  636. fmt.Println("原来的", vAct.RoadshowTitle)
  637. fmt.Println("处理的", activityName)
  638. for _, v := range list {
  639. if v.UserPhone != "" {
  640. item := new(models.CygxActivityAttendanceDetail)
  641. item.ActivityId = activityDetail.ActivityId
  642. item.RealName = v.UserName
  643. item.Mobile = v.UserPhone
  644. item.CompanyName = v.Company
  645. //item.SellerName = sellerName
  646. item.FirstMeetingTime = v.FirstWatchTime
  647. item.LastMeetingTime = v.LastWatchTime
  648. item.Duration = utils.GetAttendanceDetailSeconds(v.JoinTime)
  649. if v.JoinType == 1 {
  650. item.MeetingTypeStr = "网络"
  651. } else {
  652. item.MeetingTypeStr = "电话"
  653. }
  654. item.MeetingAuthentication = v.AuthInfo
  655. if v.DataType == 1 {
  656. item.MeetingStatusStr = "直播"
  657. } else {
  658. item.MeetingStatusStr = "回放"
  659. }
  660. item.Position = v.Occupation
  661. item.UseridEntity = v.UseridEntity
  662. item.CreateTime = time.Now()
  663. mobileStr += "'" + v.UserPhone + "'" + ","
  664. needAddAttendanc = append(needAddAttendanc, item)
  665. }
  666. }
  667. mobileStr = strings.TrimRight(mobileStr, ",")
  668. if mobileStr == "" {
  669. mobileStr = "1"
  670. }
  671. listUser, err := models.GetWxUserOutboundMobile(mobileStr)
  672. if err != nil {
  673. fmt.Println("GetWxUserOutboundMobile Err:", err.Error())
  674. return err
  675. }
  676. for k, v := range needAddAttendanc {
  677. for _, v2 := range listUser {
  678. if v2.OutboundMobile == v.Mobile || v2.Mobile == v.Mobile {
  679. if needAddAttendanc[k].CompanyId == 0 {
  680. needAddAttendanc[k].CompanyId = v2.CompanyId
  681. needAddAttendanc[k].SellerName = v2.SellerName
  682. needAddAttendanc[k].CompanyName = v2.CompanyName
  683. needAddAttendanc[k].IsMeetingStr = 1
  684. }
  685. }
  686. }
  687. }
  688. //fmt.Println(mobileStr)
  689. //参会记录
  690. err = models.AddAttendancDetail(needAddAttendanc, activityDetail.ActivityId, mobileStr)
  691. if err != nil {
  692. fmt.Println("AddAttendancDetail Err:", err.Error())
  693. return err
  694. }
  695. ////处理是否限制报名
  696. err = AddCygxActivityRestrictSignupByAdmin(activityDetail.ActivityId)
  697. if err != nil {
  698. fmt.Println("AddCygxActivityRestrictSignupByAdmin Err:", err.Error())
  699. return err
  700. }
  701. }
  702. }
  703. }
  704. }
  705. configCode := "jin_meng_activity_id"
  706. detail, err := models.GetConfigByCode(configCode)
  707. if err != nil {
  708. return err
  709. }
  710. fmt.Println(detail.ConfigValue)
  711. //获取需要处理的活动
  712. listActivity, err := models.GetActivityListByDateTime(startDate, endDate, activityIds, detail.ConfigValue)
  713. if err != nil {
  714. fmt.Println("GetTacticsList Err:", err.Error())
  715. return err
  716. }
  717. //通过本地去找进门财经的数据
  718. for _, vAct := range listActivity {
  719. doTime := utils.TimeRemoveHms2(vAct.ActivityTime)
  720. findStartDate := doTime + " 00:00:00"
  721. findEndDate := doTime + " 23:59:59"
  722. nameSlice := strings.Split(vAct.ActivityName, "】")
  723. //对于手动匹配到的活动数据也要更新
  724. var activityName string
  725. if len(nameSlice) > 1 {
  726. if vAct.JmcjRoadshowTitle != "" {
  727. activityName = vAct.JmcjRoadshowTitle
  728. } else {
  729. activityName = nameSlice[len(nameSlice)-1]
  730. }
  731. //activityName = nameSlice[len(nameSlice)-1]
  732. if activityName != "" {
  733. list, err := models.GetRoadshowDataList(activityName, findStartDate, findEndDate)
  734. if err != nil {
  735. fmt.Println("GetTacticsList Err:", err.Error())
  736. return err
  737. }
  738. needAddAttendanc := make([]*models.CygxActivityAttendanceDetail, 0)
  739. var mobileStr string
  740. if len(list) > 0 {
  741. fmt.Println("原来的1", vAct.ActivityName)
  742. fmt.Println("处理的2", activityName)
  743. for _, v := range list {
  744. if v.UserPhone != "" {
  745. item := new(models.CygxActivityAttendanceDetail)
  746. item.ActivityId = vAct.ActivityId
  747. item.RealName = v.UserName
  748. item.Mobile = v.UserPhone
  749. item.CompanyName = v.Company
  750. //item.SellerName = sellerName
  751. item.FirstMeetingTime = v.FirstWatchTime
  752. item.LastMeetingTime = v.LastWatchTime
  753. item.Duration = utils.GetAttendanceDetailSeconds(v.JoinTime)
  754. if v.JoinType == 1 {
  755. item.MeetingTypeStr = "网络"
  756. } else {
  757. item.MeetingTypeStr = "电话"
  758. }
  759. item.MeetingAuthentication = v.AuthInfo
  760. if v.DataType == 1 {
  761. item.MeetingStatusStr = "直播"
  762. } else {
  763. item.MeetingStatusStr = "回放"
  764. }
  765. item.Position = v.Occupation
  766. item.UseridEntity = v.UseridEntity
  767. item.CreateTime = time.Now()
  768. mobileStr += "'" + v.UserPhone + "'" + ","
  769. needAddAttendanc = append(needAddAttendanc, item)
  770. }
  771. }
  772. mobileStr = strings.TrimRight(mobileStr, ",")
  773. if mobileStr == "" {
  774. mobileStr = "1"
  775. }
  776. listUser, err := models.GetWxUserOutboundMobile(mobileStr)
  777. if err != nil {
  778. fmt.Println("GetWxUserOutboundMobile Err:", err.Error())
  779. return err
  780. }
  781. for k, v := range needAddAttendanc {
  782. for _, v2 := range listUser {
  783. if v2.OutboundMobile == v.Mobile || v2.Mobile == v.Mobile {
  784. if needAddAttendanc[k].CompanyId == 0 {
  785. needAddAttendanc[k].CompanyId = v2.CompanyId
  786. needAddAttendanc[k].SellerName = v2.SellerName
  787. needAddAttendanc[k].CompanyName = v2.CompanyName
  788. needAddAttendanc[k].IsMeetingStr = 1
  789. }
  790. }
  791. }
  792. }
  793. //参会记录
  794. err = models.AddAttendancDetail(needAddAttendanc, vAct.ActivityId, mobileStr)
  795. if err != nil {
  796. fmt.Println("AddAttendancDetail Err:", err.Error())
  797. return err
  798. }
  799. ////处理是否限制报名
  800. err = AddCygxActivityRestrictSignupByAdmin(vAct.ActivityId)
  801. if err != nil {
  802. fmt.Println("AddCygxActivityRestrictSignupByAdmin Err:", err.Error())
  803. return err
  804. }
  805. activityIds += strconv.Itoa(vAct.ActivityId) + ","
  806. }
  807. }
  808. }
  809. }
  810. activityIds = strings.TrimRight(activityIds, ",")
  811. if activityIds != "" {
  812. detailList, err := models.GetActivityAttendanceDetailList(activityIds)
  813. if err != nil {
  814. fmt.Println("GetActivityAttendanceDetailList Err:", err.Error())
  815. return err
  816. }
  817. //添加报名日志 (下载使用)
  818. err = models.AddCygxActivityMeetDetailLogOnlineByList(detailList, activityIds)
  819. if err != nil {
  820. fmt.Println("AddCygxActivityMeetDetailLogOnline Err:", err.Error())
  821. return err
  822. }
  823. }
  824. fmt.Println("结束路演同步")
  825. return
  826. }
  827. //判断是否加入黑名单
  828. func AddCygxActivityRestrictSignupByAdmin(activityId int) (err error) {
  829. total, err := models.GetActivitySignupNomeetingCount(activityId)
  830. if err != nil {
  831. utils.FileLog.Info("用户限制报名失败,Err:%s,%s", err.Error())
  832. fmt.Println(" Err:", err.Error())
  833. return err
  834. }
  835. if total == 0 {
  836. return err
  837. }
  838. mobileList, _ := models.GetUserMeetingMobile(activityId)
  839. if len(mobileList) >= 0 {
  840. for _, v := range mobileList {
  841. totalRestrict, err := models.GetRestrictSignupCountByUid(v.UserId)
  842. if err != nil {
  843. fmt.Println(" Err:", err.Error())
  844. utils.FileLog.Info("用户限制报名失败,Err:%s,%s", err.Error())
  845. return err
  846. }
  847. totalNomeet, err := models.GetActivitySignupNomeetingCountByUid(v.UserId)
  848. if err != nil {
  849. fmt.Println(" Err:", err.Error())
  850. utils.FileLog.Info("用户限制报名失败,Err:%s,%s", err.Error())
  851. return err
  852. }
  853. if totalRestrict > 0 && totalNomeet < 3 {
  854. err = models.DeleteCygxActivityRestrictSignup(v.UserId)
  855. if err != nil {
  856. fmt.Println(" Err:", err.Error())
  857. utils.FileLog.Info("用户限制报名失败,Err:%s,%s", err.Error())
  858. return err
  859. }
  860. }
  861. }
  862. }
  863. list, err := models.GetActivitySignupNomeetingCountList(activityId)
  864. if err != nil {
  865. utils.FileLog.Info("用户限制报名失败,Err:%s,%s", err.Error())
  866. fmt.Println(" 用户限制报名失败 Err:", err.Error())
  867. return err
  868. }
  869. for _, v := range list {
  870. totalRestrict, err := models.GetRestrictSignupCountByUid(v.UserId)
  871. if err != nil {
  872. fmt.Println(" Err:", err.Error())
  873. utils.FileLog.Info("用户限制报名失败,Err:%s,%s", err.Error())
  874. return err
  875. }
  876. totalNomeet, err := models.GetActivitySignupNomeetingCountByUid(v.UserId)
  877. if err != nil {
  878. fmt.Println(" Err:", err.Error())
  879. utils.FileLog.Info("用户限制报名失败,Err:%s,%s", err.Error())
  880. return err
  881. }
  882. if totalNomeet >= 3 {
  883. if totalRestrict == 0 {
  884. infoUser, err := models.GetUserAndCompanyNameList(v.UserId)
  885. if err != nil {
  886. fmt.Println(" Err:", err.Error())
  887. utils.FileLog.Info("用户限制报名失败,Err:%s,%s", err.Error())
  888. return err
  889. }
  890. if infoUser != nil {
  891. item := new(models.CygxActivityRestrictSignup)
  892. item.UserId = infoUser.UserId
  893. item.CreateTime = time.Now()
  894. item.Mobile = infoUser.Mobile
  895. item.Email = infoUser.Email
  896. item.CompanyId = infoUser.CompanyId
  897. item.CompanyName = infoUser.CompanyName
  898. item.IsRestrict = 1
  899. err = models.AddCygxActivityRestrictSignup(item)
  900. if err != nil {
  901. fmt.Println(" Err:", err.Error())
  902. utils.FileLog.Info("用户限制报名失败,Err:%s,%s", err.Error())
  903. return err
  904. }
  905. }
  906. }
  907. }
  908. }
  909. return
  910. }
  911. //活动带问提醒
  912. func SendActivityAskApplyTemplateMsg(applyName, applyTime, askContent, activityName, openId string, activityId int) (err error) {
  913. var msg string
  914. defer func() {
  915. if err != nil {
  916. go utils.SendEmail("发送模版消息失败"+time.Now().Format("2006-01-02 15:04:05"), msg+";Err:"+err.Error(), utils.EmailSendToUsers)
  917. }
  918. if msg != "" {
  919. utils.FileLog.Info("发送模版消息失败,msg:%s", msg)
  920. }
  921. }()
  922. var accessToken string
  923. if utils.RunMode == "release" {
  924. accessToken, err = models.GetWxAccessTokenByXzs()
  925. if err != nil {
  926. msg = "GetWxAccessToken Err:" + err.Error()
  927. return
  928. }
  929. if accessToken == "" {
  930. msg = "accessToken is empty"
  931. return
  932. }
  933. } else {
  934. accessToken, err = models.GetWxAccessToken()
  935. if err != nil {
  936. msg = "GetWxAccessToken Err:" + err.Error()
  937. return
  938. }
  939. if accessToken == "" {
  940. msg = "accessToken is empty"
  941. return
  942. }
  943. }
  944. sendUrl := "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" + accessToken
  945. sendMap := make(map[string]interface{})
  946. sendData := make(map[string]interface{})
  947. first := "有新的客户提问"
  948. keyword1 := applyName
  949. keyword2 := "-"
  950. keyword3 := applyTime
  951. keyword4 := askContent
  952. remark := activityName
  953. fontColor := "#D9001B"
  954. sendData["first"] = map[string]interface{}{"value": first, "color": fontColor}
  955. sendData["keyword1"] = map[string]interface{}{"value": keyword1, "color": fontColor}
  956. sendData["keyword2"] = map[string]interface{}{"value": keyword2, "color": fontColor}
  957. sendData["keyword3"] = map[string]interface{}{"value": keyword3, "color": fontColor}
  958. sendData["keyword4"] = map[string]interface{}{"value": keyword4, "color": fontColor}
  959. sendData["remark"] = map[string]interface{}{"value": remark, "color": fontColor}
  960. if utils.RunMode == "release" {
  961. sendMap["template_id"] = utils.WxMsgTemplateIdApplyXzs
  962. } else {
  963. sendMap["template_id"] = utils.WxMsgTemplateIdApply
  964. }
  965. sendMap["miniprogram"] = map[string]interface{}{"appid": utils.WxAppId, "pagepath": "activityPages/activityDetail/activityDetail?id=" + strconv.Itoa(activityId)}
  966. sendMap["data"] = sendData
  967. sendTemplateMsg(sendUrl, openId, sendMap)
  968. fmt.Println("send end")
  969. return
  970. }
  971. //专项产业调研模板消息推送
  972. func SendSpecialTemplateMsg(applyName, applyTime, mobile, activityName, openId, resource string) (err error) {
  973. var msg string
  974. defer func() {
  975. if err != nil {
  976. go utils.SendEmail("发送模版消息失败"+time.Now().Format("2006-01-02 15:04:05"), msg+";Err:"+err.Error(), utils.EmailSendToUsers)
  977. }
  978. if msg != "" {
  979. utils.FileLog.Info("发送模版消息失败,msg:%s", msg)
  980. }
  981. }()
  982. var accessToken string
  983. if utils.RunMode == "release" {
  984. accessToken, err = models.GetWxAccessTokenByXzs()
  985. if err != nil {
  986. msg = "GetWxAccessToken Err:" + err.Error()
  987. return
  988. }
  989. if accessToken == "" {
  990. msg = "accessToken is empty"
  991. return
  992. }
  993. } else {
  994. accessToken, err = models.GetWxAccessToken()
  995. if err != nil {
  996. msg = "GetWxAccessToken Err:" + err.Error()
  997. return
  998. }
  999. if accessToken == "" {
  1000. msg = "accessToken is empty"
  1001. return
  1002. }
  1003. }
  1004. sendUrl := "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" + accessToken
  1005. sendMap := make(map[string]interface{})
  1006. sendData := make(map[string]interface{})
  1007. var first string
  1008. if resource == "sale" {
  1009. first = "有客户对专项调研感兴趣"
  1010. } else {
  1011. first = "有5家公司预报名专项调研"
  1012. }
  1013. keyword1 := applyName
  1014. keyword2 := mobile
  1015. keyword3 := applyTime
  1016. keyword4 := activityName
  1017. fontColor := "#D9001B"
  1018. sendData["first"] = map[string]interface{}{"value": first, "color": fontColor}
  1019. sendData["keyword1"] = map[string]interface{}{"value": keyword1, "color": fontColor}
  1020. sendData["keyword2"] = map[string]interface{}{"value": keyword2, "color": fontColor}
  1021. sendData["keyword3"] = map[string]interface{}{"value": keyword3, "color": fontColor}
  1022. sendData["keyword4"] = map[string]interface{}{"value": keyword4, "color": fontColor}
  1023. if utils.RunMode == "release" {
  1024. sendMap["template_id"] = utils.WxMsgTemplateIdApplyXzs
  1025. } else {
  1026. sendMap["template_id"] = utils.WxMsgTemplateIdApply
  1027. }
  1028. sendMap["data"] = sendData
  1029. sendTemplateMsg(sendUrl, openId, sendMap)
  1030. return
  1031. }