report.go 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833
  1. package services
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "eta_gn/eta_task/models"
  6. "eta_gn/eta_task/models/report"
  7. "eta_gn/eta_task/services/alarm_msg"
  8. "eta_gn/eta_task/services/eta_bridge"
  9. "eta_gn/eta_task/utils"
  10. "fmt"
  11. "golang.org/x/net/context"
  12. "html"
  13. "strconv"
  14. "strings"
  15. "time"
  16. )
  17. // UpdateReportEs 更新报告/章节Es
  18. func UpdateReportEs(reportId int, publishState int) (err error) {
  19. if reportId <= 0 {
  20. return
  21. }
  22. reportInfo, err := models.GetReportByReportId(reportId)
  23. if err != nil {
  24. return
  25. }
  26. categories := ""
  27. if reportInfo.HasChapter == 1 {
  28. // 晨周报
  29. chapterList, tmpErr := models.GetPublishedChapterListByReportId(reportInfo.Id)
  30. if tmpErr != nil {
  31. return
  32. }
  33. if len(chapterList) > 0 {
  34. // 更新章节的es数据
  35. for _, chapterInfo := range chapterList {
  36. err = updateReportChapterEsByChapter(chapterInfo)
  37. if err != nil {
  38. return
  39. }
  40. }
  41. }
  42. } else {
  43. //if utils.BusinessCode == utils.BusinessCodeRelease || utils.BusinessCode == utils.BusinessCodeSandbox {
  44. permissionList, tmpErr := models.GetChartPermissionNameFromMappingByKeyword("rddp", reportInfo.ClassifyIdSecond)
  45. if tmpErr != nil {
  46. return
  47. }
  48. categoryArr := make([]string, 0)
  49. for i := 0; i < len(permissionList); i++ {
  50. categoryArr = append(categoryArr, permissionList[i].PermissionName)
  51. }
  52. aliasArr, _ := addCategoryAliasToArr(categoryArr)
  53. categories = strings.Join(aliasArr, ",")
  54. //}
  55. }
  56. // 最小单位的分类id
  57. minClassifyId, minClassifyName, err := getMinClassify(reportInfo)
  58. if err != nil {
  59. return
  60. }
  61. // 新增报告ES
  62. esReport := &models.ElasticReportDetail{
  63. ReportId: reportInfo.Id,
  64. ReportChapterId: 0,
  65. Title: reportInfo.Title,
  66. Abstract: reportInfo.Abstract,
  67. BodyContent: utils.TrimHtml(html.UnescapeString(reportInfo.Content)),
  68. PublishTime: reportInfo.PublishTime.Format(utils.FormatDateTime),
  69. PublishState: publishState,
  70. Author: reportInfo.Author,
  71. ClassifyIdFirst: reportInfo.ClassifyIdFirst,
  72. ClassifyNameFirst: reportInfo.ClassifyNameFirst,
  73. ClassifyIdSecond: reportInfo.ClassifyIdSecond,
  74. ClassifyNameSecond: reportInfo.ClassifyNameSecond,
  75. ClassifyId: minClassifyId,
  76. ClassifyName: minClassifyName,
  77. Categories: categories,
  78. StageStr: strconv.Itoa(reportInfo.Stage),
  79. }
  80. docId := fmt.Sprintf("%d-%d", reportInfo.Id, 0)
  81. if err = EsAddOrEditReport(utils.EsReportIndexName, docId, esReport); err != nil {
  82. return
  83. }
  84. return
  85. }
  86. // addCategoryAliasToArr 品种别名
  87. func addCategoryAliasToArr(categoryArr []string) (aliasArr []string, err error) {
  88. aliasArr = categoryArr
  89. if len(categoryArr) > 0 {
  90. for i := 0; i < len(categoryArr); i++ {
  91. if strings.Contains(categoryArr[i], "沥青") {
  92. aliasArr = append(aliasArr, "BU")
  93. }
  94. if strings.Contains(categoryArr[i], "MEG") {
  95. aliasArr = append(aliasArr, "EG", "乙二醇")
  96. }
  97. if strings.Contains(categoryArr[i], "聚酯") {
  98. aliasArr = append(aliasArr, "长丝", "短纤", "瓶片")
  99. }
  100. if strings.Contains(categoryArr[i], "纯苯+苯乙烯") {
  101. aliasArr = append(aliasArr, "EB")
  102. }
  103. if strings.Contains(categoryArr[i], "聚乙烯") {
  104. aliasArr = append(aliasArr, "PP", "PE")
  105. }
  106. if strings.Contains(categoryArr[i], "玻璃纯碱") {
  107. aliasArr = append(aliasArr, "玻璃", "纯碱", "FG", "SA")
  108. }
  109. if strings.Contains(categoryArr[i], "甲醇") {
  110. aliasArr = append(aliasArr, "甲醇", "MA")
  111. }
  112. if strings.Contains(categoryArr[i], "橡胶") {
  113. aliasArr = append(aliasArr, "橡胶", "RU")
  114. }
  115. }
  116. }
  117. return
  118. }
  119. // updateReportChapterEsByChapter
  120. // @Description: 通过章节详情更新报告章节ES
  121. // @author: Roc
  122. // @datetime 2024-06-20 13:16:11
  123. // @param chapterInfo *models.ReportChapter
  124. // @return err error
  125. func updateReportChapterEsByChapter(chapterInfo *models.ReportChapter) (err error) {
  126. // 章节对应的品种
  127. obj := report.ReportChapterPermissionMapping{}
  128. permissionList, tmpErr := obj.GetPermissionItemListById(chapterInfo.ReportChapterId)
  129. if tmpErr != nil {
  130. return
  131. }
  132. categoryArr := make([]string, 0)
  133. if len(permissionList) > 0 {
  134. for ii := 0; ii < len(permissionList); ii++ {
  135. categoryArr = append(categoryArr, permissionList[ii].ChartPermissionName)
  136. }
  137. }
  138. aliasArr, _ := addCategoryAliasToArr(categoryArr)
  139. categories := strings.Join(aliasArr, ",")
  140. // 新增/编辑ES
  141. esChapter := &models.ElasticReportDetail{
  142. ReportId: chapterInfo.ReportId,
  143. ReportChapterId: chapterInfo.ReportChapterId,
  144. Title: chapterInfo.Title,
  145. Abstract: chapterInfo.Abstract,
  146. BodyContent: utils.TrimHtml(html.UnescapeString(chapterInfo.Content)),
  147. PublishTime: chapterInfo.PublishTime.Format(utils.FormatDateTime),
  148. PublishState: chapterInfo.PublishState,
  149. Author: chapterInfo.Author,
  150. ClassifyIdFirst: chapterInfo.ClassifyIdFirst,
  151. ClassifyNameFirst: chapterInfo.ClassifyNameFirst,
  152. ClassifyIdSecond: 0,
  153. ClassifyNameSecond: "",
  154. ClassifyId: chapterInfo.ClassifyIdFirst,
  155. ClassifyName: chapterInfo.ClassifyNameFirst,
  156. Categories: categories,
  157. StageStr: strconv.Itoa(chapterInfo.Stage),
  158. }
  159. chapterDocId := fmt.Sprintf("%d-%d", chapterInfo.ReportId, chapterInfo.ReportChapterId)
  160. if err = EsAddOrEditReport(utils.EsReportIndexName, chapterDocId, esChapter); err != nil {
  161. return
  162. }
  163. return
  164. }
  165. // PublishReport 定时发布研报-每秒
  166. func PublishReport(cont context.Context) (err error) {
  167. errMsgList := make([]string, 0)
  168. defer func() {
  169. if err != nil {
  170. go alarm_msg.SendAlarmMsg("PublishReport-定时发布研报失败, ErrMsg:\n"+err.Error(), 3)
  171. }
  172. }()
  173. now := time.Now().Format(utils.FormatDateTimeMinute)
  174. startTime := now + ":00"
  175. endTime := now + ":59"
  176. afterDate := time.Now().AddDate(0, -1, 0).Format(utils.FormatDate) //限制一下,只查询最近一个月的
  177. list, err := models.GetPrePublishedReports(startTime, endTime, afterDate)
  178. if err != nil {
  179. return
  180. }
  181. listLen := len(list)
  182. if listLen == 0 {
  183. return
  184. }
  185. // 比对时间(分钟),时间相等则发布并推送
  186. for i := 0; i < listLen; i++ {
  187. item := list[i]
  188. var publishTime time.Time
  189. if item.MsgIsSend == 1 && !item.PublishTime.IsZero() { //如果报告曾经发布过,并且已经发送过模版消息,则章节的发布时间为报告的发布时间
  190. publishTime = item.PublishTime
  191. } else {
  192. publishTime = time.Now()
  193. }
  194. //if item.HasChapter == 1 && (item.ChapterType == utils.REPORT_TYPE_DAY || item.ChapterType == utils.REPORT_TYPE_WEEK) {
  195. // continue
  196. //}
  197. var tmpErr error
  198. if item.HasChapter == 1 { // 章节类型的报告
  199. // 发布报告和章节
  200. item.State = 2
  201. item.PublishTime = publishTime
  202. item.ModifyTime = time.Now().Local()
  203. updateCols := make([]string, 0)
  204. updateCols = append(updateCols, "PublishTime", "State", "ModifyTime")
  205. tmpErr = models.PublishReportAndChapter(item, true, updateCols)
  206. } else {
  207. tmpErr = models.PublishReportById(item.Id, publishTime)
  208. }
  209. if tmpErr != nil {
  210. errMsgList = append(errMsgList, fmt.Sprint("报告发布失败,ID:", item.Id, ",ErrMsg:", tmpErr.Error()))
  211. } else {
  212. go handleByPublishReport(item)
  213. }
  214. }
  215. return
  216. }
  217. // handleByPublishReport
  218. // @Description: 报告发布
  219. // @author: Roc
  220. // @datetime 2024-06-28 13:26:51
  221. // @param item *models.Report
  222. // @param publishTime time.Time
  223. // @return err error
  224. func handleByPublishReport(item *models.Report) {
  225. recordItem := &models.ReportStateRecord{
  226. ReportId: item.Id,
  227. ReportType: 1,
  228. State: 2,
  229. AdminId: item.AdminId,
  230. AdminName: item.AdminName,
  231. CreateTime: time.Now(),
  232. }
  233. // 添加记录
  234. _, _ = models.AddReportStateRecord(recordItem)
  235. if item.HasChapter == 1 {
  236. // 生产报告章节音频
  237. _ = UpdateChaptersVideoByReportId(item.Id)
  238. } else {
  239. // 生成音频
  240. if item.VideoUrl == "" {
  241. _ = CreateVideo(item)
  242. }
  243. }
  244. // 更新报告Es
  245. err := UpdateReportEs(item.Id, 2)
  246. if err != nil {
  247. utils.FileLog.Error("UpdateReportEs, 更新报告Es失败, ReportId:%s, Err:%s", item.Id, err.Error())
  248. }
  249. // 判断是否未发送模版消息,并且配置了立即推送模版消息的报告需要推送
  250. if utils.SendWxTemplateEnable == "1" {
  251. if item.MsgIsSend == 0 && item.PreMsgSend == 1 {
  252. _ = ReportSendTemplateMsg(item.Id)
  253. }
  254. }
  255. return
  256. }
  257. func ReportSendTemplateMsg(reportId int) (err error) {
  258. defer func() {
  259. if err != nil {
  260. msg := fmt.Sprintf("ReportSendTemplateMsg, 发送报告模版消息失败, ReportId:%s, Err:%s", reportId, err.Error())
  261. utils.FileLog.Error(msg)
  262. go alarm_msg.SendAlarmMsg(msg, 3)
  263. }
  264. }()
  265. reportInfo, err := models.GetReportByReportId(reportId)
  266. if err != nil {
  267. err = errors.New("查询报告失败 Err:" + err.Error())
  268. return
  269. }
  270. if reportInfo.MsgIsSend == 1 {
  271. err = errors.New("模板消息已推送,请勿重复操作")
  272. return
  273. }
  274. videoNameDate := `(` + time.Now().Format("0102") + `)`
  275. err = models.UpdateReportPublishTime(reportId, videoNameDate)
  276. if err != nil {
  277. err = errors.New("修改发布时间失败,Err:" + err.Error())
  278. return
  279. }
  280. if reportInfo.HasChapter > 0 {
  281. err = models.UpdateReportChapterPublishTime(reportId, videoNameDate)
  282. if err != nil {
  283. err = errors.New("修改发布时间失败,Err:" + err.Error())
  284. return
  285. }
  286. }
  287. err = sendMiniProgramReportWxMsg(reportInfo)
  288. if err != nil {
  289. err = errors.New("发送失败,Err:" + err.Error())
  290. return
  291. }
  292. err = models.ModifyReportMsgIsSend(reportId)
  293. if err != nil {
  294. err = errors.New("发送失败,Err:" + err.Error())
  295. return
  296. }
  297. return
  298. }
  299. // sendMiniProgramReportWxMsg 推送报告微信模板消息-小程序链接
  300. func sendMiniProgramReportWxMsg(report *models.Report) (err error) {
  301. reportId := report.Id
  302. var msg string
  303. reportIdStr := strconv.Itoa(reportId)
  304. defer func() {
  305. if err != nil {
  306. fmt.Println("msg:", msg)
  307. utils.FileLog.Error(fmt.Sprintf("SendMiniProgramReportWxMsg, 发送报告模版消息失败, ReportId:%s, Err:%s", reportIdStr, err.Error()))
  308. go alarm_msg.SendAlarmMsg("SendMiniProgramReportWxMsg发送报告模版消息失败;"+"ReportId:"+reportIdStr+",Err:"+err.Error()+";msg:"+msg, 3)
  309. //go utils.SendEmail("SendMiniProgramReportWxMsg发送报告模版消息失败"+"【"+utils.APPNAME+"】"+"【"+utils.RunMode+"】"+time.Now().Format("2006-01-02 15:04:05"), "ReportId:"+reportIdStr+";"+msg+";Err:"+err.Error(), toUser)
  310. }
  311. }()
  312. utils.FileLog.Info("%s", "services SendMsg")
  313. if report == nil {
  314. utils.FileLog.Info("报告信息不存在")
  315. return
  316. }
  317. var openIdArr []string
  318. minClassifyId, _, err := getMinClassify(report)
  319. if err != nil {
  320. msg = "获取报告的最小分类失败 err:" + err.Error()
  321. return err
  322. }
  323. // 判断分类是否存在
  324. _, err = models.GetClassifyById(minClassifyId)
  325. if err != nil {
  326. msg = "获取报告分类失败 err:" + err.Error()
  327. return err
  328. }
  329. // 获取该分类关联的openid列表
  330. openIdArr, err = models.GetOpenIdArrByClassifyId(minClassifyId)
  331. if err != nil {
  332. msg = "GetOpenIdArrByClassifyNameSecond err:" + err.Error()
  333. return err
  334. }
  335. // TODO 弘则的文案是不是要去掉
  336. title := fmt.Sprintf("弘则%s", report.ClassifyNameFirst)
  337. if CheckTwoWeekOrMonthReport(report.ClassifyIdFirst, report.ClassifyNameFirst) {
  338. title = fmt.Sprintf("弘则%s", report.ClassifyNameSecond)
  339. }
  340. //redirectUrl := utils.TemplateRedirectUrl + strconv.Itoa(reportId)
  341. first := fmt.Sprintf("Hi,最新一期%s已上线,欢迎查看", report.ClassifyNameFirst)
  342. keyword1 := title
  343. keyword2 := report.Title
  344. keyword3 := report.PublishTime.Format(utils.FormatDateTime)
  345. keyword4 := report.Abstract
  346. var wxAppPath string
  347. if report.ChapterType == utils.REPORT_TYPE_WEEK {
  348. wxAppPath = fmt.Sprintf("pages-report/chapterList?reportId=%s", reportIdStr)
  349. } else {
  350. wxAppPath = fmt.Sprintf("pages-report/reportDetail?reportId=%s", reportIdStr)
  351. }
  352. sendInfo := new(SendWxTemplate)
  353. sendInfo.First = first
  354. sendInfo.Keyword1 = keyword1
  355. sendInfo.Keyword2 = keyword2
  356. sendInfo.Keyword3 = keyword3
  357. sendInfo.Keyword4 = keyword4
  358. sendInfo.TemplateId = utils.TemplateIdByProduct
  359. sendInfo.RedirectUrl = wxAppPath
  360. sendInfo.Resource = wxAppPath
  361. sendInfo.SendType = utils.TEMPLATE_MSG_REPORT
  362. sendInfo.OpenIdArr = openIdArr
  363. sendInfo.RedirectTarget = 1
  364. err = SendTemplateMsgV2(sendInfo)
  365. return
  366. }
  367. // CheckTwoWeekOrMonthReport 校验推送报告是否为双周报或者月报
  368. func CheckTwoWeekOrMonthReport(classifyId int, classifyName string) (ok bool) {
  369. if utils.RunMode == "debug" {
  370. miniStrArr := []string{
  371. "双周报", "月报",
  372. }
  373. if utils.InArrayByStr(miniStrArr, classifyName) {
  374. ok = true
  375. }
  376. } else {
  377. // 此处生产环境用ID主要是担心分类改了名字...
  378. IdArr := []int{
  379. 96, 112,
  380. }
  381. if utils.InArrayByInt(IdArr, classifyId) {
  382. ok = true
  383. }
  384. }
  385. return
  386. }
  387. // ClearReportSaveLog 每天清理两周前的报告保存日志
  388. func ClearReportSaveLog(cont context.Context) (err error) {
  389. defer func() {
  390. if err != nil {
  391. tips := fmt.Sprintf("报告日志记录, SaveReportLogs error: %s", err.Error())
  392. fmt.Println(tips)
  393. go alarm_msg.SendAlarmMsg(tips, 2)
  394. }
  395. }()
  396. twoWeek := time.Now().Local().AddDate(0, 0, -14).Format(utils.FormatDateTime)
  397. e := models.ClearReportSaveLog(twoWeek)
  398. if e != nil {
  399. err = fmt.Errorf("ClearReportSaveLog: %s", e.Error())
  400. }
  401. return
  402. }
  403. // UpdateChaptersVideoByReportId
  404. // @Description: 更新报告章节音频
  405. // @author: Roc
  406. // @datetime 2024-06-28 13:52:56
  407. // @param reportId int
  408. // @return err error
  409. func UpdateChaptersVideoByReportId(reportId int) (err error) {
  410. defer func() {
  411. if err != nil {
  412. utils.FileLog.Error("UpdateChaptersVideo, reportId:%v, Err:%s", reportId, err.Error())
  413. go alarm_msg.SendAlarmMsg(fmt.Sprintf("更新章节音频失败, 报告ID: %v; Err: "+err.Error(), reportId), 3)
  414. }
  415. }()
  416. chapterList, err := models.GetChapterListByReportId(reportId)
  417. if err != nil {
  418. return
  419. }
  420. // 生成video
  421. nowTime := time.Now()
  422. updateCols := make([]string, 0)
  423. updateCols = append(updateCols, "VideoUrl", "VideoName", "VideoSize", "VideoPlaySeconds")
  424. for i := 0; i < len(chapterList); i++ {
  425. item := chapterList[i]
  426. // 忽略已有音频的章节
  427. if item.VideoUrl != "" && item.VideoName != "" && item.VideoSize != "" && item.VideoPlaySeconds != "" {
  428. continue
  429. }
  430. videoUrl, videoName, videoSize, videoPlaySeconds, e := CreateReportVideo(item.Title, html.UnescapeString(item.Content), nowTime.Format(utils.FormatDateTime))
  431. if e != nil {
  432. err = e
  433. return
  434. }
  435. item.VideoUrl = videoUrl
  436. item.VideoName = videoName
  437. item.VideoSize = videoSize
  438. item.VideoPlaySeconds = fmt.Sprintf("%.2f", videoPlaySeconds)
  439. if e = item.UpdateChapter(updateCols); e != nil {
  440. err = e
  441. }
  442. }
  443. return
  444. }
  445. // getMinClassify
  446. // @Description: 获取最小分类ID
  447. // @author: Roc
  448. // @datetime 2024-06-20 09:23:19
  449. // @param reportInfo *models.Report
  450. // @return minClassifyId int
  451. // @return minClassifyName string
  452. // @return err error
  453. func getMinClassify(reportInfo *models.Report) (minClassifyId int, minClassifyName string, err error) {
  454. defer func() {
  455. if err != nil {
  456. utils.FileLog.Error("获取最小分类ID失败,报告ID:%d,Err:%s", reportInfo.Id, err.Error())
  457. }
  458. }()
  459. minClassifyId = reportInfo.ClassifyIdThird
  460. minClassifyName = reportInfo.ClassifyNameThird
  461. if minClassifyId <= 0 {
  462. minClassifyId = reportInfo.ClassifyIdSecond
  463. minClassifyName = reportInfo.ClassifyNameSecond
  464. }
  465. if minClassifyId <= 0 {
  466. minClassifyId = reportInfo.ClassifyIdFirst
  467. minClassifyName = reportInfo.ClassifyNameFirst
  468. }
  469. if minClassifyId <= 0 {
  470. err = errors.New("分类异常")
  471. }
  472. return
  473. }
  474. // ReportWriteRemind 报告撰写提醒
  475. func ReportWriteRemind(cont context.Context) (err error) {
  476. defer func() {
  477. if err != nil {
  478. tips := fmt.Sprintf("ReportWriteRemind-报告撰写提醒失败, ErrMsg: %v", err)
  479. fmt.Println(tips)
  480. utils.FileLog.Info(tips)
  481. }
  482. }()
  483. timeNow := time.Now()
  484. timeClock := timeNow.Format("15:04")
  485. // 查询需要提醒的分类
  486. classifies := make([]*models.Classify, 0)
  487. {
  488. ob := new(models.Classify)
  489. cond := ` AND is_remind = ? AND remind_time = ?`
  490. pars := make([]interface{}, 0)
  491. pars = append(pars, 1, timeClock)
  492. list, e := ob.GetItemsByCondition(cond, pars, []string{}, "")
  493. if e != nil {
  494. err = fmt.Errorf("获取分类失败, %v", e)
  495. return
  496. }
  497. classifies = list
  498. }
  499. if len(classifies) == 0 {
  500. return
  501. }
  502. var reportClassifyIds, pptClassifyIds []int
  503. classifyMatch := make(map[string]bool)
  504. for _, v := range classifies {
  505. if v.ClassifyType == utils.ReportTypeDefault {
  506. // levelPath作为下面报告的匹配
  507. var levelIds []int
  508. var firstId, secondId, thirdId int
  509. levelArr := strings.Split(v.LevelPath, ",")
  510. for _, l := range levelArr {
  511. id, _ := strconv.Atoi(l)
  512. levelIds = append(levelIds, id)
  513. }
  514. if len(levelIds) > 2 {
  515. firstId = levelIds[0]
  516. secondId = levelIds[1]
  517. thirdId = levelIds[2]
  518. }
  519. if len(levelIds) > 1 {
  520. firstId = levelIds[0]
  521. secondId = levelIds[1]
  522. }
  523. if len(levelIds) > 0 {
  524. firstId = levelIds[0]
  525. }
  526. classifyMatch[fmt.Sprintf("%d-%d-%d", firstId, secondId, thirdId)] = true
  527. reportClassifyIds = append(reportClassifyIds, v.Id)
  528. continue
  529. }
  530. if v.ClassifyType == utils.ReportTypePPT {
  531. pptClassifyIds = append(pptClassifyIds, v.Id)
  532. continue
  533. }
  534. }
  535. // 查询需要提醒的报告
  536. remindReports := make([]*models.Report, 0)
  537. if len(reportClassifyIds) > 0 {
  538. ob := new(models.Report)
  539. cond := ` AND report_source = ? AND state = ? AND topic_end_time >= ?`
  540. pars := make([]interface{}, 0)
  541. pars = append(pars, utils.ReportSourceOuter, models.ReportStateWaitSubmit, timeNow)
  542. list, e := ob.GetItemsByCondition(cond, pars, []string{"id", "title", "admin_id", "classify_id_first", "classify_id_second", "classify_id_third"}, "")
  543. if e != nil {
  544. err = fmt.Errorf("获取待提醒报告失败, %v", e)
  545. return
  546. }
  547. for _, v := range list {
  548. k := fmt.Sprintf("%d-%d-%d", v.ClassifyIdFirst, v.ClassifyIdSecond, v.ClassifyIdThird)
  549. if !classifyMatch[k] {
  550. continue
  551. }
  552. remindReports = append(remindReports, v)
  553. }
  554. }
  555. // 查询需要提醒的PPT
  556. remindPpts := make([]*models.PptV2, 0)
  557. if len(pptClassifyIds) > 0 {
  558. ob := new(models.PptV2)
  559. cond := ` AND report_source = ? AND state = ? AND topic_end_time >= ? AND classify_id IN (?)`
  560. pars := make([]interface{}, 0)
  561. pars = append(pars, utils.ReportSourceOuter, models.ReportStateWaitSubmit, timeNow, pptClassifyIds)
  562. list, e := ob.GetItemsByCondition(cond, pars, models.PptReportQueryFields, "")
  563. if e != nil {
  564. err = fmt.Errorf("获取待提醒报告失败, %v", e)
  565. return
  566. }
  567. remindPpts = list
  568. }
  569. if len(remindReports) == 0 && len(remindPpts) == 0 {
  570. return
  571. }
  572. reportMessages := make([]*models.ReportMessage, 0)
  573. // 报告提醒
  574. if len(remindReports) > 0 {
  575. var remindReportIds []int
  576. for _, v := range remindReports {
  577. remindReportIds = append(remindReportIds, v.Id)
  578. }
  579. // 获取协作人
  580. grantOb := new(models.ReportGrant)
  581. grantCond := ` AND report_id IN (?)`
  582. grantPars := make([]interface{}, 0)
  583. grantPars = append(grantPars, remindReportIds)
  584. grants, e := grantOb.GetItemsByCondition(grantCond, grantPars, []string{}, "")
  585. if e != nil {
  586. err = fmt.Errorf("获取报告协作人失败, %v", e)
  587. return
  588. }
  589. reportGrants := make(map[int][]int)
  590. for _, v := range grants {
  591. reportGrants[v.ReportId] = append(reportGrants[v.ReportId], v.GrantId)
  592. }
  593. // 推送消息
  594. for _, v := range remindReports {
  595. var userIds []int
  596. userIds = append(userIds, v.AdminId)
  597. for _, p := range reportGrants[v.Id] {
  598. if !utils.InArrayByInt(userIds, p) {
  599. userIds = append(userIds, p)
  600. }
  601. }
  602. for _, u := range userIds {
  603. m := new(models.ReportMessage)
  604. m.SendUserId = 0
  605. m.ReceiveUserId = u
  606. m.Content = fmt.Sprintf("您有一篇【%s】待编辑,请点击查看", v.Title)
  607. m.ReportType = utils.ReportTypeDefault
  608. m.ReportId = v.Id
  609. m.MessageType = models.ReportMessageTypeWriteNotice
  610. m.CreateTime = time.Now()
  611. m.ModifyTime = time.Now()
  612. reportMessages = append(reportMessages, m)
  613. }
  614. }
  615. }
  616. // PPT提醒
  617. if len(remindPpts) > 0 {
  618. for _, v := range remindPpts {
  619. // 收信人
  620. var userIds []int
  621. userIds = append(userIds, v.AdminId)
  622. partnerArr := strings.Split(v.CollaborateUsers, ",")
  623. for _, p := range partnerArr {
  624. id, _ := strconv.Atoi(p)
  625. if id <= 0 {
  626. continue
  627. }
  628. if !utils.InArrayByInt(userIds, id) {
  629. userIds = append(userIds, id)
  630. }
  631. }
  632. for _, u := range userIds {
  633. m := new(models.ReportMessage)
  634. m.SendUserId = 0
  635. m.ReceiveUserId = u
  636. m.Content = fmt.Sprintf("您有一篇【%s】待编辑,请点击查看", v.Title)
  637. m.ReportType = utils.ReportTypePPT
  638. m.ReportId = v.PptId
  639. m.MessageType = models.ReportMessageTypeWriteNotice
  640. m.CreateTime = time.Now()
  641. m.ModifyTime = time.Now()
  642. reportMessages = append(reportMessages, m)
  643. }
  644. }
  645. }
  646. if len(reportMessages) == 0 {
  647. return
  648. }
  649. messageOb := new(models.ReportMessage)
  650. if e := messageOb.CreateMulti(reportMessages); e != nil {
  651. err = fmt.Errorf("新增报告提醒失败, %v", e)
  652. return
  653. }
  654. // OA消息
  655. go func() {
  656. _ = SendOaReportMessage(reportMessages)
  657. }()
  658. return
  659. }
  660. // SendOaReportMessage 推送OA报告消息
  661. func SendOaReportMessage(reportMessages []*models.ReportMessage) (err error) {
  662. defer func() {
  663. if err != nil {
  664. tips := fmt.Sprintf("SendOaReportMessage-报告OA消息推送失败, ErrMsg: %v", err)
  665. fmt.Println(tips)
  666. utils.FileLog.Info(tips)
  667. }
  668. }()
  669. // 未开启则不管
  670. conf, e := models.GetBusinessConfByKey(models.BusinessOpenOaMsg)
  671. if e != nil {
  672. utils.FileLog.Info(fmt.Sprintf("获取OA消息开关失败, %v", e))
  673. return
  674. }
  675. var sendOa bool
  676. if conf != nil && conf.ConfVal == "true" {
  677. sendOa = true
  678. }
  679. if !sendOa {
  680. return
  681. }
  682. hostConf, e := models.GetBusinessConfByKey(models.BusinessOaReportHost)
  683. if e != nil {
  684. utils.FileLog.Info(fmt.Sprintf("获取OA消息跳转Host失败, %v", e))
  685. return
  686. }
  687. var hostUrl string
  688. if hostConf != nil {
  689. hostUrl = hostConf.ConfVal
  690. }
  691. if hostUrl == "" {
  692. utils.FileLog.Info("OA消息跳转Host未配置")
  693. return
  694. }
  695. reportUrl := fmt.Sprintf("%s/reportNew", hostUrl)
  696. pptUrl := fmt.Sprintf("%s/pptlist", hostUrl)
  697. // 查询用户,匹配工号
  698. adminIdOut := make(map[int]*models.Admin)
  699. {
  700. adminOb := new(models.Admin)
  701. admins, e := adminOb.GetItemsByCondition(``, make([]interface{}, 0), []string{"admin_id", "real_name", "out_id"}, "")
  702. if e != nil {
  703. err = fmt.Errorf("获取员工列表失败, %v", e)
  704. return
  705. }
  706. for _, v := range admins {
  707. adminIdOut[v.AdminId] = v
  708. }
  709. }
  710. // 推送OA
  711. oaMessages := make([]*models.OaReportMessage, 0)
  712. for _, v := range reportMessages {
  713. // 接收用户
  714. receiver := adminIdOut[v.ReceiveUserId]
  715. if receiver == nil || (receiver != nil && receiver.AdminId <= 0) {
  716. utils.FileLog.Info(fmt.Sprintf("SendOaReportMessage-OA推送用户异常, UserId: %d", v.ReceiveUserId))
  717. continue
  718. }
  719. oaMessage := new(models.OaReportMessage)
  720. oaMessage.ReceiveUserId = receiver.AdminId
  721. oaMessage.ReportType = v.ReportType
  722. oaMessage.ReportId = v.ReportId
  723. oaMessage.Source = models.OaReportMessageSourceRemind
  724. oaMessage.SendStatus = models.OaReportMessageStatusFail
  725. oaMessage.CreateTime = time.Now()
  726. oaMessage.ModifyTime = time.Now()
  727. // OA请求参数
  728. var params eta_bridge.PostOAReq
  729. params.AppPersonId = receiver.OutId
  730. params.AppPersonName = receiver.RealName
  731. if v.ReportType == utils.ReportTypeDefault {
  732. params.AppTaskUrl = reportUrl
  733. }
  734. if v.ReportType == utils.ReportTypePPT {
  735. params.AppTaskUrl = pptUrl
  736. }
  737. params.TaskName = v.Content
  738. params.StatusName = v.Content
  739. params.Status = 1
  740. b, e := json.Marshal(params)
  741. if e != nil {
  742. oaMessage.MessageResult = fmt.Sprintf("OA推送JSON格式化失败, %v", e)
  743. oaMessages = append(oaMessages, oaMessage)
  744. continue
  745. }
  746. oaMessage.MessageParams = string(b)
  747. // OA请求
  748. resByte, e, _ := eta_bridge.HttpEtaBridgePost(utils.SyncOaTodoPath, params)
  749. if e != nil {
  750. oaMessage.MessageResult = fmt.Sprintf("OA推送POST请求失败, %v", e)
  751. oaMessages = append(oaMessages, oaMessage)
  752. continue
  753. }
  754. oaMessage.MessageResult = string(resByte)
  755. var sendRes eta_bridge.PostOAResp
  756. if e = json.Unmarshal(resByte, &sendRes); e != nil {
  757. oaMessages = append(oaMessages, oaMessage)
  758. continue
  759. }
  760. if sendRes.Code != 200 {
  761. oaMessages = append(oaMessages, oaMessage)
  762. continue
  763. }
  764. oaMessage.TaskId = sendRes.Data
  765. oaMessage.SendStatus = models.OaReportMessageStatusSuccess
  766. oaMessages = append(oaMessages, oaMessage)
  767. }
  768. if len(oaMessages) == 0 {
  769. return
  770. }
  771. oaMessageOb := new(models.OaReportMessage)
  772. if e := oaMessageOb.CreateMulti(oaMessages); e != nil {
  773. err = fmt.Errorf("新增OA待办记录失败, %v", e)
  774. }
  775. return
  776. }