package services import ( "errors" "eta/eta_task/models" "eta/eta_task/models/report" "eta/eta_task/services/alarm_msg" "eta/eta_task/utils" "fmt" "golang.org/x/net/context" "html" "strconv" "strings" "time" ) // UpdateReportEs 更新报告/章节Es func UpdateReportEs(reportId int, publishState int) (err error) { if reportId <= 0 { return } reportInfo, err := models.GetReportByReportId(reportId) if err != nil { return } categories := "" if reportInfo.HasChapter == 1 { // 晨周报 chapterList, tmpErr := models.GetPublishedChapterListByReportId(reportInfo.Id) if tmpErr != nil { return } if len(chapterList) > 0 { // 更新章节的es数据 for _, chapterInfo := range chapterList { err = updateReportChapterEsByChapter(chapterInfo) if err != nil { return } } } } else { //if utils.BusinessCode == utils.BusinessCodeRelease || utils.BusinessCode == utils.BusinessCodeSandbox { permissionList, tmpErr := models.GetChartPermissionNameFromMappingByKeyword("rddp", reportInfo.ClassifyIdSecond) if tmpErr != nil { return } categoryArr := make([]string, 0) for i := 0; i < len(permissionList); i++ { categoryArr = append(categoryArr, permissionList[i].PermissionName) } aliasArr, _ := addCategoryAliasToArr(categoryArr) categories = strings.Join(aliasArr, ",") //} } // 最小单位的分类id minClassifyId, minClassifyName, err := getMinClassify(reportInfo) if err != nil { return } // 新增报告ES esReport := &models.ElasticReportDetail{ ReportId: reportInfo.Id, ReportChapterId: 0, Title: reportInfo.Title, Abstract: reportInfo.Abstract, BodyContent: utils.TrimHtml(html.UnescapeString(reportInfo.Content)), PublishTime: reportInfo.PublishTime.Format(utils.FormatDateTime), PublishState: publishState, Author: reportInfo.Author, ClassifyIdFirst: reportInfo.ClassifyIdFirst, ClassifyNameFirst: reportInfo.ClassifyNameFirst, ClassifyIdSecond: reportInfo.ClassifyIdSecond, ClassifyNameSecond: reportInfo.ClassifyNameSecond, ClassifyId: minClassifyId, ClassifyName: minClassifyName, Categories: categories, StageStr: strconv.Itoa(reportInfo.Stage), } docId := fmt.Sprintf("%d-%d", reportInfo.Id, 0) if err = EsAddOrEditReport(utils.EsReportIndexName, docId, esReport); err != nil { return } return } // addCategoryAliasToArr 品种别名 func addCategoryAliasToArr(categoryArr []string) (aliasArr []string, err error) { aliasArr = categoryArr if len(categoryArr) > 0 { for i := 0; i < len(categoryArr); i++ { if strings.Contains(categoryArr[i], "沥青") { aliasArr = append(aliasArr, "BU") } if strings.Contains(categoryArr[i], "MEG") { aliasArr = append(aliasArr, "EG", "乙二醇") } if strings.Contains(categoryArr[i], "聚酯") { aliasArr = append(aliasArr, "长丝", "短纤", "瓶片") } if strings.Contains(categoryArr[i], "纯苯+苯乙烯") { aliasArr = append(aliasArr, "EB") } if strings.Contains(categoryArr[i], "聚乙烯") { aliasArr = append(aliasArr, "PP", "PE") } if strings.Contains(categoryArr[i], "玻璃纯碱") { aliasArr = append(aliasArr, "玻璃", "纯碱", "FG", "SA") } if strings.Contains(categoryArr[i], "甲醇") { aliasArr = append(aliasArr, "甲醇", "MA") } if strings.Contains(categoryArr[i], "橡胶") { aliasArr = append(aliasArr, "橡胶", "RU") } } } return } // updateReportChapterEsByChapter // @Description: 通过章节详情更新报告章节ES // @author: Roc // @datetime 2024-06-20 13:16:11 // @param chapterInfo *models.ReportChapter // @return err error func updateReportChapterEsByChapter(chapterInfo *models.ReportChapter) (err error) { // 章节对应的品种 obj := report.ReportChapterPermissionMapping{} permissionList, tmpErr := obj.GetPermissionItemListById(chapterInfo.ReportChapterId) if tmpErr != nil { return } categoryArr := make([]string, 0) if len(permissionList) > 0 { for ii := 0; ii < len(permissionList); ii++ { categoryArr = append(categoryArr, permissionList[ii].ChartPermissionName) } } aliasArr, _ := addCategoryAliasToArr(categoryArr) categories := strings.Join(aliasArr, ",") // 新增/编辑ES esChapter := &models.ElasticReportDetail{ ReportId: chapterInfo.ReportId, ReportChapterId: chapterInfo.ReportChapterId, Title: chapterInfo.Title, Abstract: chapterInfo.Abstract, BodyContent: utils.TrimHtml(html.UnescapeString(chapterInfo.Content)), PublishTime: chapterInfo.PublishTime.Format(utils.FormatDateTime), PublishState: chapterInfo.PublishState, Author: chapterInfo.Author, ClassifyIdFirst: chapterInfo.ClassifyIdFirst, ClassifyNameFirst: chapterInfo.ClassifyNameFirst, ClassifyIdSecond: 0, ClassifyNameSecond: "", ClassifyId: chapterInfo.ClassifyIdFirst, ClassifyName: chapterInfo.ClassifyNameFirst, Categories: categories, StageStr: strconv.Itoa(chapterInfo.Stage), } chapterDocId := fmt.Sprintf("%d-%d", chapterInfo.ReportId, chapterInfo.ReportChapterId) if err = EsAddOrEditReport(utils.EsReportIndexName, chapterDocId, esChapter); err != nil { return } return } // PublishReport 定时发布研报-每秒 func PublishReport(cont context.Context) (err error) { errMsgList := make([]string, 0) defer func() { if err != nil { go alarm_msg.SendAlarmMsg("PublishReport-定时发布研报失败, ErrMsg:\n"+err.Error(), 3) } }() now := time.Now().Format(utils.FormatDateTimeMinute) startTime := now + ":00" endTime := now + ":59" afterDate := time.Now().AddDate(0, -1, 0).Format(utils.FormatDate) //限制一下,只查询最近一个月的 list, err := models.GetPrePublishedReports(startTime, endTime, afterDate) if err != nil { return } listLen := len(list) if listLen == 0 { return } // 比对时间(分钟),时间相等则发布并推送 for i := 0; i < listLen; i++ { item := list[i] var publishTime time.Time if item.MsgIsSend == 1 && !item.PublishTime.IsZero() { //如果报告曾经发布过,并且已经发送过模版消息,则章节的发布时间为报告的发布时间 publishTime = item.PublishTime } else { publishTime = time.Now() } //if item.HasChapter == 1 && (item.ChapterType == utils.REPORT_TYPE_DAY || item.ChapterType == utils.REPORT_TYPE_WEEK) { // continue //} var tmpErr error if item.HasChapter == 1 { // 章节类型的报告 // 发布报告和章节 item.State = 2 item.PublishTime = publishTime item.ModifyTime = time.Now().Local() updateCols := make([]string, 0) updateCols = append(updateCols, "PublishTime", "State", "ModifyTime") tmpErr = models.PublishReportAndChapter(item, true, updateCols) } else { tmpErr = models.PublishReportById(item.Id, publishTime) } if tmpErr != nil { errMsgList = append(errMsgList, fmt.Sprint("报告发布失败,ID:", item.Id, ",ErrMsg:", tmpErr.Error())) } else { go handleByPublishReport(item) } } return } // handleByPublishReport // @Description: 报告发布 // @author: Roc // @datetime 2024-06-28 13:26:51 // @param item *models.Report // @param publishTime time.Time // @return err error func handleByPublishReport(item *models.Report) { recordItem := &models.ReportStateRecord{ ReportId: item.Id, ReportType: 1, State: 2, AdminId: item.AdminId, AdminName: item.AdminName, CreateTime: time.Now(), } // 添加记录 _, _ = models.AddReportStateRecord(recordItem) if item.HasChapter == 1 { // 生产报告章节音频 _ = UpdateChaptersVideoByReportId(item.Id) } else { // 生成音频 if item.VideoUrl == "" { _ = CreateVideo(item) } } // 更新报告Es err := UpdateReportEs(item.Id, 2) if err != nil { utils.FileLog.Error("UpdateReportEs, 更新报告Es失败, ReportId:%s, Err:%s", item.Id, err.Error()) } // 判断是否未发送模版消息,并且配置了立即推送模版消息的报告需要推送 if utils.SendWxTemplateEnable == "1" { if item.MsgIsSend == 0 && item.PreMsgSend == 1 { _ = ReportSendTemplateMsg(item.Id) } } return } // PublishReportTest 定时发布研报-每秒 /*func PublishReportTest() (err error) { defer func() { if err != nil { fmt.Println(err.Error()) } }() item, err := models.GetReportById(3331) if err != nil { return } // 判断是否未发送模版消息,并且配置了立即推送模版消息的报告需要推送 if item.MsgIsSend == 0 && item.PreMsgSend == 1 { err = ReportSendTemplateMsg(item.Id) if err != nil { return } } return }*/ func ReportSendTemplateMsg(reportId int) (err error) { defer func() { if err != nil { msg := fmt.Sprintf("ReportSendTemplateMsg, 发送报告模版消息失败, ReportId:%s, Err:%s", reportId, err.Error()) utils.FileLog.Error(msg) go alarm_msg.SendAlarmMsg(msg, 3) } }() reportInfo, err := models.GetReportByReportId(reportId) if err != nil { err = errors.New("查询报告失败 Err:" + err.Error()) return } if reportInfo.MsgIsSend == 1 { err = errors.New("模板消息已推送,请勿重复操作") return } videoNameDate := `(` + time.Now().Format("0102") + `)` err = models.UpdateReportPublishTime(reportId, videoNameDate) if err != nil { err = errors.New("修改发布时间失败,Err:" + err.Error()) return } if reportInfo.HasChapter > 0 { err = models.UpdateReportChapterPublishTime(reportId, videoNameDate) if err != nil { err = errors.New("修改发布时间失败,Err:" + err.Error()) return } } err = sendMiniProgramReportWxMsg(reportInfo) if err != nil { err = errors.New("发送失败,Err:" + err.Error()) return } err = models.ModifyReportMsgIsSend(reportId) if err != nil { err = errors.New("发送失败,Err:" + err.Error()) return } return } // sendMiniProgramReportWxMsg 推送报告微信模板消息-小程序链接 func sendMiniProgramReportWxMsg(report *models.Report) (err error) { reportId := report.Id var msg string reportIdStr := strconv.Itoa(reportId) defer func() { if err != nil { fmt.Println("msg:", msg) utils.FileLog.Error(fmt.Sprintf("SendMiniProgramReportWxMsg, 发送报告模版消息失败, ReportId:%s, Err:%s", reportIdStr, err.Error())) go alarm_msg.SendAlarmMsg("SendMiniProgramReportWxMsg发送报告模版消息失败;"+"ReportId:"+reportIdStr+",Err:"+err.Error()+";msg:"+msg, 3) //go utils.SendEmail("SendMiniProgramReportWxMsg发送报告模版消息失败"+"【"+utils.APPNAME+"】"+"【"+utils.RunMode+"】"+time.Now().Format("2006-01-02 15:04:05"), "ReportId:"+reportIdStr+";"+msg+";Err:"+err.Error(), toUser) } }() utils.FileLog.Info("%s", "services SendMsg") if report == nil { utils.FileLog.Info("报告信息不存在") return } var openIdArr []string // 如果是弘则,且报告分类是晨报,那么就所有人推送 if (utils.BusinessCode == utils.BusinessCodeRelease || utils.BusinessCode == utils.BusinessCodeSandbox || utils.BusinessCode == utils.BusinessCodeDebug) && report.ClassifyNameFirst == "晨报" { // 如果是章节,那就推送所有用户 openIdArr, err = models.GetOpenIdArr() if err != nil { msg = "get GetOpenIdArr err:" + err.Error() return } } else { minClassifyId, _, err := getMinClassify(report) if err != nil { msg = "获取报告的最小分类失败 err:" + err.Error() return err } // 判断分类是否存在 _, err = models.GetClassifyById(minClassifyId) if err != nil { msg = "获取报告分类失败 err:" + err.Error() return err } // 获取该分类关联的openid列表 openIdArr, err = models.GetOpenIdArrByClassifyId(minClassifyId) if err != nil { msg = "GetOpenIdArrByClassifyNameSecond err:" + err.Error() return err } } // TODO 弘则的文案是不是要去掉 title := fmt.Sprintf("弘则%s", report.ClassifyNameFirst) if CheckTwoWeekOrMonthReport(report.ClassifyIdFirst, report.ClassifyNameFirst) { title = fmt.Sprintf("弘则%s", report.ClassifyNameSecond) } //redirectUrl := utils.TemplateRedirectUrl + strconv.Itoa(reportId) first := fmt.Sprintf("Hi,最新一期%s已上线,欢迎查看", report.ClassifyNameFirst) keyword1 := title keyword2 := report.Title keyword3 := report.PublishTime.Format(utils.FormatDateTime) keyword4 := report.Abstract var wxAppPath string if report.ChapterType == utils.REPORT_TYPE_WEEK { wxAppPath = fmt.Sprintf("pages-report/chapterList?reportId=%s", reportIdStr) } else { wxAppPath = fmt.Sprintf("pages-report/reportDetail?reportId=%s", reportIdStr) } sendInfo := new(SendWxTemplate) sendInfo.First = first sendInfo.Keyword1 = keyword1 sendInfo.Keyword2 = keyword2 sendInfo.Keyword3 = keyword3 sendInfo.Keyword4 = keyword4 sendInfo.TemplateId = utils.TemplateIdByProduct sendInfo.RedirectUrl = wxAppPath sendInfo.Resource = wxAppPath sendInfo.SendType = utils.TEMPLATE_MSG_REPORT sendInfo.OpenIdArr = openIdArr sendInfo.RedirectTarget = 1 err = SendTemplateMsgV2(sendInfo) return } // CheckTwoWeekOrMonthReport 校验推送报告是否为双周报或者月报 func CheckTwoWeekOrMonthReport(classifyId int, classifyName string) (ok bool) { if utils.RunMode == "debug" { miniStrArr := []string{ "双周报", "月报", } if utils.InArrayByStr(miniStrArr, classifyName) { ok = true } } else { // 此处生产环境用ID主要是担心分类改了名字... IdArr := []int{ 96, 112, } if utils.InArrayByInt(IdArr, classifyId) { ok = true } } return } // ClearReportSaveLog 每天清理两周前的报告保存日志 func ClearReportSaveLog(cont context.Context) (err error) { defer func() { if err != nil { tips := fmt.Sprintf("报告日志记录, SaveReportLogs error: %s", err.Error()) fmt.Println(tips) go alarm_msg.SendAlarmMsg(tips, 2) } }() twoWeek := time.Now().Local().AddDate(0, 0, -14).Format(utils.FormatDateTime) e := models.ClearReportSaveLog(twoWeek) if e != nil { err = fmt.Errorf("ClearReportSaveLog: %s", e.Error()) } return } // UpdateChaptersVideoByReportId // @Description: 更新报告章节音频 // @author: Roc // @datetime 2024-06-28 13:52:56 // @param reportId int // @return err error func UpdateChaptersVideoByReportId(reportId int) (err error) { defer func() { if err != nil { utils.FileLog.Error("UpdateChaptersVideo, reportId:%v, Err:%s", reportId, err.Error()) go alarm_msg.SendAlarmMsg(fmt.Sprintf("更新章节音频失败, 报告ID: %v; Err: "+err.Error(), reportId), 3) } }() chapterList, err := models.GetChapterListByReportId(reportId) if err != nil { return } // 生成video nowTime := time.Now() updateCols := make([]string, 0) updateCols = append(updateCols, "VideoUrl", "VideoName", "VideoSize", "VideoPlaySeconds") for i := 0; i < len(chapterList); i++ { item := chapterList[i] // 忽略已有音频的章节 if item.VideoUrl != "" && item.VideoName != "" && item.VideoSize != "" && item.VideoPlaySeconds != "" { continue } videoUrl, videoName, videoSize, videoPlaySeconds, e := CreateReportVideo(item.Title, html.UnescapeString(item.Content), nowTime.Format(utils.FormatDateTime)) if e != nil { err = e return } item.VideoUrl = videoUrl item.VideoName = videoName item.VideoSize = videoSize item.VideoPlaySeconds = fmt.Sprintf("%.2f", videoPlaySeconds) if e = item.UpdateChapter(updateCols); e != nil { err = e } } return } // getMinClassify // @Description: 获取最小分类ID // @author: Roc // @datetime 2024-06-20 09:23:19 // @param reportInfo *models.Report // @return minClassifyId int // @return minClassifyName string // @return err error func getMinClassify(reportInfo *models.Report) (minClassifyId int, minClassifyName string, err error) { defer func() { if err != nil { utils.FileLog.Error("获取最小分类ID失败,报告ID:%d,Err:%s", reportInfo.Id, err.Error()) } }() minClassifyId = reportInfo.ClassifyIdThird minClassifyName = reportInfo.ClassifyNameThird if minClassifyId <= 0 { minClassifyId = reportInfo.ClassifyIdSecond minClassifyName = reportInfo.ClassifyNameSecond } if minClassifyId <= 0 { minClassifyId = reportInfo.ClassifyIdFirst minClassifyName = reportInfo.ClassifyNameFirst } if minClassifyId <= 0 { err = errors.New("分类异常") } return }