Browse Source

Merge branch 'eta/1.8.3'

Roc 7 months ago
parent
commit
fe6de95df5

+ 13 - 0
models/db.go

@@ -4,6 +4,7 @@ import (
 	"eta/eta_task/models/data_manage"
 	"eta/eta_task/models/data_manage/edb_refresh"
 	"eta/eta_task/models/data_manage/future_good"
+	"eta/eta_task/models/report"
 	"eta/eta_task/utils"
 	_ "github.com/go-sql-driver/mysql"
 	"time"
@@ -78,6 +79,9 @@ func init() {
 	//注册持仓分析 数据表
 	initTradePositionTop()
 
+	// 研报数据表
+	initReport()
+
 	// 智能研报数据表
 	initSmartReport()
 
@@ -155,6 +159,15 @@ func initTradePositionTop() {
 	)
 }
 
+// initReport 注册研报数据表
+func initReport() {
+	orm.RegisterModel(
+		new(Report),
+		new(ReportChapter),
+		new(report.ReportChapterPermissionMapping), // 报告章节的权限关系表
+	)
+}
+
 // initSmartReport 注册智能研报数据表
 func initSmartReport() {
 	orm.RegisterModel(

+ 48 - 45
models/report.go

@@ -35,6 +35,8 @@ type Report struct {
 	PreMsgSend         int       `description:"定时发布成功后是否立即推送模版消息:0否,1是"`
 	AdminId            int
 	AdminName          string `description:"系统用户名称"`
+	ClassifyIdThird    int    `description:"三级分类id"`
+	ClassifyNameThird  string `description:"三级分类名称"`
 }
 
 func GetReportById(reportId int) (item *ReportDetail, err error) {
@@ -137,46 +139,6 @@ func ModifyReportVideo(reportId int, videoUrl, videoName, videoSize string, play
 	return
 }
 
-// ReportChapter 报告章节
-type ReportChapter struct {
-	ReportChapterId   int       `orm:"column(report_chapter_id);pk" description:"报告章节ID"`
-	ReportId          int       `description:"报告ID"`
-	ReportType        string    `description:"报告类型 day-晨报 week-周报"`
-	ClassifyIdFirst   int       `description:"一级分类id"`
-	ClassifyNameFirst string    `description:"一级分类名称"`
-	TypeId            int       `description:"品种ID"`
-	TypeName          string    `description:"品种名称"`
-	Title             string    `description:"标题"`
-	Abstract          string    `description:"摘要"`
-	AddType           int       `description:"新增方式:1:新增报告,2:继承报告"`
-	Author            string    `description:"作者"`
-	Content           string    `description:"内容"`
-	ContentSub        string    `description:"内容前两个章节"`
-	Stage             int       `description:"期数"`
-	Trend             string    `description:"趋势观点"`
-	Sort              int       `description:"排序: 数值越小越靠前"`
-	IsEdit            int       `description:"是否已编辑 0-待编辑 1-已编辑"`
-	PublishState      int       `description:"发布状态 1-待发布,2-已发布"`
-	PublishTime       time.Time `description:"发布时间"`
-	VideoUrl          string    `description:"音频文件URL"`
-	VideoName         string    `description:"音频文件名称"`
-	VideoPlaySeconds  string    `description:"音频播放时长"`
-	VideoSize         string    `description:"音频文件大小,单位M"`
-	VideoKind         int       `description:"音频生成方式:1,手动上传,2:自动生成"`
-	CreateTime        string    `description:"创建时间"`
-	ModifyTime        time.Time `description:"修改时间"`
-	OriginalVideoUrl  string    `description:"原始音频文件URL"`
-}
-
-// GetPublishedChapterListByReportId 根据ReportId获取已发布章节列表
-func GetPublishedChapterListByReportId(reportId int) (list []*ReportChapter, err error) {
-	o := orm.NewOrmUsingDB("rddp")
-	sql := ` SELECT * FROM report_chapter WHERE report_id = ? AND publish_state = 2 ORDER BY sort ASC`
-	_, err = o.Raw(sql, reportId).QueryRows(&list)
-
-	return
-}
-
 type ReportChapterTypePermission struct {
 	Id                    int       `orm:"column(id);pk" description:"主键ID"`
 	ReportChapterTypeId   int       `description:"报告章节类型ID"`
@@ -208,6 +170,8 @@ type ElasticReportDetail struct {
 	ClassifyNameFirst  string `description:"一级分类名称"`
 	ClassifyIdSecond   int    `description:"二级分类ID"`
 	ClassifyNameSecond string `description:"二级分类名称"`
+	ClassifyId         int    `description:"最小单元的分类ID"`
+	ClassifyName       string `description:"最小单元的分类名称"`
 	Categories         string `description:"关联的品种名称(包括品种别名)"`
 	StageStr           string `description:"报告期数"`
 }
@@ -217,11 +181,10 @@ type ChartPermissionMappingIdName struct {
 	PermissionName string
 }
 
-func GetChartPermissionNameFromMappingByKeyword(keyword string, source string) (list []*ChartPermissionMappingIdName, err error) {
-	o := orm.NewOrm()
-	sql := " SELECT b.chart_permission_id AS permission_id,b.permission_name FROM chart_permission_search_key_word_mapping AS a INNER JOIN chart_permission AS b ON a.chart_permission_id = b.chart_permission_id WHERE a.`from` = ? AND a.key_word = ? "
-	_, err = o.Raw(sql, source, keyword).QueryRows(&list)
-
+func GetChartPermissionNameFromMappingByKeyword(source string, classifyId int) (list []*ChartPermissionMappingIdName, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := " SELECT b.chart_permission_id AS permission_id,b.permission_name FROM chart_permission_search_key_word_mapping AS a INNER JOIN chart_permission AS b ON a.chart_permission_id = b.chart_permission_id WHERE a.`from` = ? AND a.classify_id = ? "
+	_, err = o.Raw(sql, source, classifyId).QueryRows(&list)
 	return
 }
 
@@ -265,3 +228,43 @@ func ClearReportSaveLog(date string) (err error) {
 	_, err = o.Raw(sql, date).Exec()
 	return
 }
+
+// PublishReportAndChapter 发布报告及章节
+func PublishReportAndChapter(reportInfo *Report, isPublishReport bool, cols []string) (err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	to, err := o.Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = to.Rollback()
+		} else {
+			_ = to.Commit()
+		}
+	}()
+	// 更新报告
+	if isPublishReport {
+		_, err = to.Update(reportInfo, cols...)
+		if err != nil {
+			return
+		}
+	}
+
+	// 发布该报告的所有章节
+	sql := ` UPDATE report_chapter SET publish_state = 2, publish_time = ? WHERE report_id = ?  `
+	_, err = to.Raw(sql, reportInfo.PublishTime, reportInfo.Id).Exec()
+
+	// 发布章节
+	//if len(publishIds) > 0 {
+	//	sql := ` UPDATE report_chapter SET publish_state = 2, publish_time = ? WHERE report_id = ? AND report_chapter_id IN (` + utils.GetOrmInReplace(len(publishIds)) + `) `
+	//	_, err = to.Raw(sql, reportInfo.PublishTime, reportInfo.Id, publishIds).Exec()
+	//}
+
+	//if len(unPublishIds) > 0 {
+	//	sql := ` UPDATE report_chapter SET publish_state = 1, publish_time = NULL, is_edit = 0 WHERE report_id = ? AND report_chapter_id IN (` + utils.GetOrmInReplace(len(unPublishIds)) + `) `
+	//	_, err = to.Raw(sql, reportInfo.Id, unPublishIds).Exec()
+	//}
+
+	return
+}

+ 152 - 0
models/report/report_chapter_permission_mapping.go

@@ -0,0 +1,152 @@
+package report
+
+import (
+	"eta/eta_task/utils"
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+// ReportChapterPermissionMapping
+// @Description: 报告章节的权限关系表
+type ReportChapterPermissionMapping struct {
+	ReportChapterPermissionMappingId int `orm:"column(report_chapter_permission_mapping_id)"`
+	ReportChapterId                  int `description:"报告章节的id"` // 报告章节的id
+	ChartPermissionId                int `description:"权限id"`    // 权限id
+	CreateTime                       time.Time
+}
+
+// MultiAddReportChapterPermissionMappingPermission
+// @Description: 批量添加报告品种权限用户
+// @author: Roc
+// @receiver m
+// @datetime 2024-06-04 15:36:02
+// @param reportChapterId int
+// @param list []*ReportChapterPermissionMapping
+// @return err error
+func (m ReportChapterPermissionMapping) MultiAddReportChapterPermissionMappingPermission(reportChapterId int, list []*ReportChapterPermissionMapping) (err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	to, err := o.Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = to.Rollback()
+		} else {
+			_ = to.Commit()
+		}
+	}()
+
+	sql := "DELETE from report_chapter_permission_mapping where report_chapter_id=?"
+	_, err = to.Raw(sql, reportChapterId).Exec()
+	if err != nil {
+		return
+	}
+
+	// 新增品种权限记录
+	if len(list) > 0 {
+		_, tmpErr := to.InsertMulti(500, list)
+		if tmpErr != nil {
+			err = tmpErr
+			return
+		}
+	}
+
+	return
+}
+
+// GetPermissionListById
+// @Description: 根据id获取品种权限列表
+// @author: Roc
+// @receiver m
+// @datetime 2024-06-04 15:33:58
+// @param reportChapterId int
+// @return list []*ReportChapterPermissionMapping
+// @return err error
+func (m ReportChapterPermissionMapping) GetPermissionListById(reportChapterId int) (list []*ReportChapterPermissionMapping, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := `SELECT * FROM report_chapter_permission_mapping WHERE report_chapter_id=? `
+	_, err = o.Raw(sql, reportChapterId).QueryRows(&list)
+
+	return
+}
+
+// ReportChapterPermissionItem
+// @Description: 报告章节的权限关系表(带有品种名称)
+type ReportChapterPermissionItem struct {
+	ReportChapterPermissionMappingId int    `orm:"column(report_chapter_permission_mapping_id)"`
+	ReportChapterId                  int    `description:"报告章节的id"`
+	ChartPermissionId                int    `description:"权限id"`
+	ChartPermissionName              string `description:"品种名称"`
+	CreateTime                       time.Time
+}
+
+// GetPermissionItemListById
+// @Description: 根据id获取品种权限列表(带有品种名称)
+// @author: Roc
+// @receiver m
+// @datetime 2024-06-04 15:33:58
+// @param reportChapterId int
+// @return list []*ReportChapterPermissionMapping
+// @return err error
+func (m ReportChapterPermissionMapping) GetPermissionItemListById(reportChapterId int) (list []*ReportChapterPermissionItem, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := `SELECT a.*,b.chart_permission_name FROM report_chapter_permission_mapping AS a 
+         JOIN chart_permission AS b on a.chart_permission_id=b.chart_permission_id WHERE report_chapter_id=? `
+	_, err = o.Raw(sql, reportChapterId).QueryRows(&list)
+
+	return
+}
+
+// GetPermissionListByIdList
+// @Description: 根据id列表获取品种权限列表
+// @author: Roc
+// @receiver m
+// @datetime 2024-06-04 15:33:58
+// @param reportChapterIdList []int
+// @return list []*ReportChapterPermissionMapping
+// @return err error
+func (m ReportChapterPermissionMapping) GetPermissionListByIdList(reportChapterIdList []int) (list []*ReportChapterPermissionMapping, err error) {
+	num := len(reportChapterIdList)
+	if num <= 0 {
+		return
+	}
+
+	o := orm.NewOrmUsingDB("rddp")
+	sql := `SELECT * FROM report_chapter_permission_mapping WHERE report_chapter_id in (` + utils.GetOrmInReplace(num) + `) `
+	_, err = o.Raw(sql, reportChapterIdList).QueryRows(&list)
+
+	return
+}
+
+// MultiAdd
+// @Description: 批量添加
+// @author: Roc
+// @receiver m
+// @datetime 2024-06-20 18:04:33
+// @param list []*ReportChapterPermissionMapping
+// @return err error
+func (m ReportChapterPermissionMapping) MultiAdd(list []*ReportChapterPermissionMapping) (err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	to, err := o.Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = to.Rollback()
+		} else {
+			_ = to.Commit()
+		}
+	}()
+
+	// 新增品种权限记录
+	if len(list) > 0 {
+		_, err = to.InsertMulti(500, list)
+		if err != nil {
+			return
+		}
+	}
+
+	return
+}

+ 75 - 0
models/report_chapter.go

@@ -0,0 +1,75 @@
+package models
+
+import (
+	"eta/eta_task/utils"
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+// ReportChapter 报告章节
+type ReportChapter struct {
+	ReportChapterId   int       `orm:"column(report_chapter_id);pk" description:"报告章节ID"`
+	ReportId          int       `description:"报告ID"`
+	ReportType        string    `description:"报告类型 day-晨报 week-周报"`
+	ClassifyIdFirst   int       `description:"一级分类id"`
+	ClassifyNameFirst string    `description:"一级分类名称"`
+	TypeId            int       `description:"品种ID"`
+	TypeName          string    `description:"品种名称"`
+	Title             string    `description:"标题"`
+	Abstract          string    `description:"摘要"`
+	AddType           int       `description:"新增方式:1:新增报告,2:继承报告"`
+	Author            string    `description:"作者"`
+	Content           string    `description:"内容"`
+	ContentSub        string    `description:"内容前两个章节"`
+	Stage             int       `description:"期数"`
+	Trend             string    `description:"趋势观点"`
+	Sort              int       `description:"排序: 数值越小越靠前"`
+	IsEdit            int       `description:"是否已编辑 0-待编辑 1-已编辑"`
+	PublishState      int       `description:"发布状态 1-待发布,2-已发布"`
+	PublishTime       time.Time `description:"发布时间"`
+	VideoUrl          string    `description:"音频文件URL"`
+	VideoName         string    `description:"音频文件名称"`
+	VideoPlaySeconds  string    `description:"音频播放时长"`
+	VideoSize         string    `description:"音频文件大小,单位M"`
+	VideoKind         int       `description:"音频生成方式:1,手动上传,2:自动生成"`
+	CreateTime        string    `description:"创建时间"`
+	ModifyTime        time.Time `description:"修改时间"`
+	OriginalVideoUrl  string    `description:"原始音频文件URL"`
+}
+
+// GetPublishedChapterListByReportId 根据ReportId获取已发布章节列表
+func GetPublishedChapterListByReportId(reportId int) (list []*ReportChapter, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := ` SELECT * FROM report_chapter WHERE report_id = ? AND publish_state = 2 ORDER BY sort ASC`
+	_, err = o.Raw(sql, reportId).QueryRows(&list)
+
+	return
+}
+
+// GetChapterListByReportId 根据ReportId获取章节列表
+func GetChapterListByReportId(reportId int) (list []*ReportChapter, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := ` SELECT * FROM report_chapter WHERE report_id = ? ORDER BY sort ASC`
+	_, err = o.Raw(sql, reportId).QueryRows(&list)
+
+	return
+}
+
+// GetChapterListByChapterIds 根据ReportId获取章节列表
+func GetChapterListByChapterIds(chapterIds []int) (list []*ReportChapter, err error) {
+	if len(chapterIds) == 0 {
+		return
+	}
+	o := orm.NewOrmUsingDB("rddp")
+	sql := ` SELECT * FROM report_chapter WHERE report_chapter_id IN (` + utils.GetOrmInReplace(len(chapterIds)) + `) ORDER BY sort ASC`
+	_, err = o.Raw(sql, chapterIds).QueryRows(&list)
+	return
+}
+
+// UpdateChapter 更新报表章节
+func (chapterChapterInfo *ReportChapter) UpdateChapter(cols []string) (err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	_, err = o.Update(chapterChapterInfo, cols...)
+
+	return
+}

+ 24 - 0
models/wx_template_msg.go

@@ -63,3 +63,27 @@ func GetOpenIdArrByClassifyNameSecond(classifyNameSecond string) (items []string
 	_, err = o.Raw(sql, classifyNameSecond).QueryRows(&items)
 	return
 }
+
+// GetOpenIdArrByClassifyId
+// @Description: 根据分类id获取关联的用户微信openid
+// @author: Roc
+// @datetime 2024-06-28 14:57:27
+// @param classifyId int
+// @return items []string
+// @return err error
+func GetOpenIdArrByClassifyId(classifyId int) (items []string, err error) {
+	sql := ` SELECT DISTINCT ur.open_id FROM wx_user AS wu 
+			INNER JOIN company AS c ON c.company_id = wu.company_id 
+			INNER JOIN company_product AS d ON c.company_id=d.company_id
+			INNER JOIN user_record  AS ur ON wu.user_id=ur.user_id
+			INNER JOIN company_report_permission AS e ON d.company_id=e.company_id
+			INNER JOIN chart_permission AS f ON e.chart_permission_id=f.chart_permission_id
+			INNER JOIN chart_permission_search_key_word_mapping AS g ON f.chart_permission_id=g.chart_permission_id
+			WHERE ur.open_id != "" AND ur.subscribe=1 AND ur.create_platform=1 AND  d.status IN('正式','试用','永续') AND  e.status IN('正式','试用','永续') 
+			AND g.from='rddp'
+			AND g.classify_id=?
+			ORDER BY FIELD(c.company_id, 16) DESC, ur.user_record_id ASC  `
+	o := orm.NewOrmUsingDB("weekly")
+	_, err = o.Raw(sql, classifyId).QueryRows(&items)
+	return
+}

+ 228 - 87
services/report.go

@@ -3,6 +3,7 @@ package services
 import (
 	"errors"
 	"eta/eta_task/models"
+	"eta/eta_task/models/report"
 	"eta/eta_task/services/alarm_msg"
 	"eta/eta_task/utils"
 	"fmt"
@@ -30,45 +31,17 @@ func UpdateReportEs(reportId int, publishState int) (err error) {
 			return
 		}
 		if len(chapterList) > 0 {
-			for i := 0; i < len(chapterList); i++ {
-				// 章节对应的品种
-				permissionList, tmpErr := models.GetChapterTypePermissionByTypeIdAndResearchType(chapterList[i].TypeId, chapterList[i].ReportType)
-				if tmpErr != nil {
-					return
-				}
-				categoryArr := make([]string, 0)
-				if len(permissionList) > 0 {
-					for ii := 0; ii < len(permissionList); ii++ {
-						categoryArr = append(categoryArr, permissionList[ii].PermissionName)
-					}
-				}
-				aliasArr, _ := addCategoryAliasToArr(categoryArr)
-				chapterCategories := strings.Join(aliasArr, ",")
-
-				esChapter := &models.ElasticReportDetail{
-					ReportId:           chapterList[i].ReportId,
-					ReportChapterId:    chapterList[i].ReportChapterId,
-					Title:              chapterList[i].Title,
-					Abstract:           chapterList[i].Abstract,
-					BodyContent:        utils.TrimHtml(html.UnescapeString(chapterList[i].Content)),
-					PublishTime:        chapterList[i].PublishTime.Format(utils.FormatDateTime),
-					PublishState:       chapterList[i].PublishState,
-					Author:             chapterList[i].Author,
-					ClassifyIdFirst:    chapterList[i].ClassifyIdFirst,
-					ClassifyNameFirst:  chapterList[i].ClassifyNameFirst,
-					ClassifyIdSecond:   0,
-					ClassifyNameSecond: "",
-					Categories:         chapterCategories,
-					StageStr:           strconv.Itoa(chapterList[i].Stage),
-				}
-				chapterDocId := fmt.Sprintf("%d-%d", reportInfo.Id, chapterList[i].ReportChapterId)
-				if err = EsAddOrEditReport(utils.EsReportIndexName, chapterDocId, esChapter); err != nil {
+			// 更新章节的es数据
+			for _, chapterInfo := range chapterList {
+				err = updateReportChapterEsByChapter(chapterInfo)
+				if err != nil {
 					return
 				}
 			}
 		}
 	} else {
-		permissionList, tmpErr := models.GetChartPermissionNameFromMappingByKeyword(reportInfo.ClassifyNameSecond, "rddp")
+		//if utils.BusinessCode == utils.BusinessCodeRelease || utils.BusinessCode == utils.BusinessCodeSandbox {
+		permissionList, tmpErr := models.GetChartPermissionNameFromMappingByKeyword("rddp", reportInfo.ClassifyIdSecond)
 		if tmpErr != nil {
 			return
 		}
@@ -78,6 +51,13 @@ func UpdateReportEs(reportId int, publishState int) (err error) {
 		}
 		aliasArr, _ := addCategoryAliasToArr(categoryArr)
 		categories = strings.Join(aliasArr, ",")
+		//}
+	}
+
+	// 最小单位的分类id
+	minClassifyId, minClassifyName, err := getMinClassify(reportInfo)
+	if err != nil {
+		return
 	}
 
 	// 新增报告ES
@@ -94,6 +74,8 @@ func UpdateReportEs(reportId int, publishState int) (err error) {
 		ClassifyNameFirst:  reportInfo.ClassifyNameFirst,
 		ClassifyIdSecond:   reportInfo.ClassifyIdSecond,
 		ClassifyNameSecond: reportInfo.ClassifyNameSecond,
+		ClassifyId:         minClassifyId,
+		ClassifyName:       minClassifyName,
 		Categories:         categories,
 		StageStr:           strconv.Itoa(reportInfo.Stage),
 	}
@@ -139,8 +121,58 @@ func addCategoryAliasToArr(categoryArr []string) (aliasArr []string, err error)
 	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)
@@ -168,44 +200,75 @@ func PublishReport(cont context.Context) (err error) {
 		} else {
 			publishTime = time.Now()
 		}
-		if item.HasChapter == 1 && (item.ChapterType == utils.REPORT_TYPE_DAY || item.ChapterType == utils.REPORT_TYPE_WEEK) {
-			continue
+		//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 err = models.PublishReportById(item.Id, publishTime); err != nil {
-			return
+		if tmpErr != nil {
+			errMsgList = append(errMsgList, fmt.Sprint("报告发布失败,ID:", item.Id, ",ErrMsg:", tmpErr.Error()))
+		} else {
+			go handleByPublishReport(item)
 		}
+	}
 
-		go func() {
-			// 生成音频
-			if item.VideoUrl == "" {
-				_ = CreateVideo(item)
-			}
-			//// 推送找钢网
-			//if utils.RunMode == "release" && (report.ClassifyNameSecond == "知白守黑日评" || report.ClassifyNameSecond == "股债日评") {
-			//	_ = services.ZhaoGangSend(report)
-			//}
-			// 更新报告Es
-			_ = UpdateReportEs(item.Id, 2)
-
-			// 判断是否未发送模版消息,并且配置了立即推送模版消息的报告需要推送
-			if utils.SendWxTemplateEnable == "1" {
-				if item.MsgIsSend == 0 && item.PreMsgSend == 1 {
-					_ = ReportSendTemplateMsg(item.Id)
-				}
-			}
-		}()
-		recordItem := &models.ReportStateRecord{
-			ReportId:   item.Id,
-			ReportType: 1,
-			State:      2,
-			AdminId:    item.AdminId,
-			AdminName:  item.AdminName,
-			CreateTime: time.Now(),
+	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)
 		}
-		go func() {
-			_, _ = models.AddReportStateRecord(recordItem)
-		}()
 	}
+
 	return
 }
 
@@ -239,12 +302,12 @@ func ReportSendTemplateMsg(reportId int) (err error) {
 		}
 	}()
 
-	report, err := models.GetReportById(reportId)
+	reportInfo, err := models.GetReportByReportId(reportId)
 	if err != nil {
 		err = errors.New("查询报告失败 Err:" + err.Error())
 		return
 	}
-	if report.MsgIsSend == 1 {
+	if reportInfo.MsgIsSend == 1 {
 		err = errors.New("模板消息已推送,请勿重复操作")
 		return
 	}
@@ -255,7 +318,7 @@ func ReportSendTemplateMsg(reportId int) (err error) {
 		err = errors.New("修改发布时间失败,Err:" + err.Error())
 		return
 	}
-	if report.HasChapter > 0 {
+	if reportInfo.HasChapter > 0 {
 		err = models.UpdateReportChapterPublishTime(reportId, videoNameDate)
 		if err != nil {
 			err = errors.New("修改发布时间失败,Err:" + err.Error())
@@ -263,7 +326,7 @@ func ReportSendTemplateMsg(reportId int) (err error) {
 		}
 	}
 
-	err = sendMiniProgramReportWxMsg(report)
+	err = sendMiniProgramReportWxMsg(reportInfo)
 	if err != nil {
 		err = errors.New("发送失败,Err:" + err.Error())
 		return
@@ -277,7 +340,7 @@ func ReportSendTemplateMsg(reportId int) (err error) {
 }
 
 // sendMiniProgramReportWxMsg 推送报告微信模板消息-小程序链接
-func sendMiniProgramReportWxMsg(report *models.ReportDetail) (err error) {
+func sendMiniProgramReportWxMsg(report *models.Report) (err error) {
 	reportId := report.Id
 	var msg string
 	reportIdStr := strconv.Itoa(reportId)
@@ -297,33 +360,36 @@ func sendMiniProgramReportWxMsg(report *models.ReportDetail) (err error) {
 	}
 
 	var openIdArr []string
-	if report.ClassifyIdSecond <= 0 {
+	// 如果是弘则,且报告分类是晨报,那么就所有人推送
+	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 {
-		classify, err := models.GetClassifyById(report.ClassifyIdSecond)
+		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
 		}
-		if classify.IsMassSend == 1 {
-			openIdArr, err = models.GetOpenIdArr()
-			if err != nil {
-				msg = "get GetOpenIdArr err:" + err.Error()
-				return err
-			}
-		} else {
-			openIdArr, err = models.GetOpenIdArrByClassifyNameSecond(report.ClassifyNameSecond)
-			if err != nil {
-				msg = "GetOpenIdArrByClassifyNameSecond 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)
@@ -332,7 +398,7 @@ func sendMiniProgramReportWxMsg(report *models.ReportDetail) (err error) {
 	first := fmt.Sprintf("Hi,最新一期%s已上线,欢迎查看", report.ClassifyNameFirst)
 	keyword1 := title
 	keyword2 := report.Title
-	keyword3 := report.PublishTime
+	keyword3 := report.PublishTime.Format(utils.FormatDateTime)
 	keyword4 := report.Abstract
 
 	var wxAppPath string
@@ -397,3 +463,78 @@ func ClearReportSaveLog(cont context.Context) (err 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
+}

+ 5 - 4
services/task.go

@@ -21,6 +21,11 @@ func Task() {
 	// 定时发布智能研报
 	publishSmartReport := task.NewTask("publishSmartReport", "0 */1 * * * *", PublishSmartReport)
 	task.AddTask("定时发布智能研报", publishSmartReport)
+
+	// 定时发布研报
+	publishReport := task.NewTask("publishReport", "0 */1 * * * *", PublishReport)
+	task.AddTask("定时发布研报", publishReport)
+
 	// 定时汇总数据源终端指标更新情况
 	setEdbSourceStatTask := task.NewTask("setEdbSourceStatTask", "0 20 19,23 * * *", data_stat.SetEdbSourceStatTask)
 	task.AddTask("数据源统计表", setEdbSourceStatTask)
@@ -94,10 +99,6 @@ func releaseTask() {
 	deleteLog := task.NewTask("syncSubStatus", "0 0 2 2 * *", DeleteLog)
 	task.AddTask("deleteLog", deleteLog)
 
-	// 定时发布研报
-	publishReport := task.NewTask("publishReport", "0 */1 * * * *", PublishReport)
-	task.AddTask("定时发布研报", publishReport)
-
 	// 定时发布英文研报
 	publishEnglishReport := task.NewTask("publishEnglishReport", "0 */1 * * * *", PublishEnglishReport)
 	task.AddTask("定时发布英文研报", publishEnglishReport)

+ 7 - 0
services/video.go

@@ -81,6 +81,13 @@ func CreateVideo(report *models.Report) (err error) {
 	//if utils.FileIsExist(savePath) {
 	//	os.Remove(savePath)
 	//}
+
+	// 如果没有文本内容,那么就不生成了
+	videoContent = strings.TrimSpace(videoContent)
+	if videoContent == `` {
+		return
+	}
+
 	contentArr := GetChineseCount(videoContent)
 	for _, v := range contentArr {
 		newText := v

+ 2 - 0
utils/constants.go

@@ -144,7 +144,9 @@ const (
 
 // 商户号
 const (
+	BusinessCodeSandbox = "E2023080700" // 试用平台
 	BusinessCodeRelease = "E2023080900" // 生产环境
+	BusinessCodeDebug   = "E2023080901" // 测试环境
 	BusinessCodeJiaYue  = "E2023092201" // 嘉悦物产
 	BusinessCodeZhongJi = "E2023110300" // 中基宁波
 )