Browse Source

Merge branch 'master' into feature/yb11.1_rai_report

# Conflicts:
#	services/report_rai.go
xyxie 1 month ago
parent
commit
387ac8944d

+ 31 - 0
cache/wechat_platform.go → cache/llm.go

@@ -51,3 +51,34 @@ func AddWechatArticleLlmOpToCache(wechatPlatformId int, source string) bool {
 	}
 	return false
 }
+
+type RagEtaReportOpOp struct {
+	Source          string
+	ReportId        int
+	ReportChapterId int
+}
+
+// RagEtaReportOpToCache
+// @Description: 将eta报告入知识库操作加入缓存
+// @author: Roc
+// @datetime 2025-04-07 15:05:22
+// @param reportId int
+// @param reportChapterId int
+// @param source string
+// @return bool
+func RagEtaReportOpToCache(reportId, reportChapterId int, source string) bool {
+	record := new(RagEtaReportOpOp)
+	record.Source = source
+	record.ReportId = reportId
+	record.ReportChapterId = reportChapterId
+	if utils.Re == nil {
+		err := utils.Rc.LPush(utils.CACHE_ETA_REPORT_KNOWLEDGE, record)
+
+		utils.FileLog.Info(fmt.Sprintf("将eta报告入知识库操作加入缓存 加入缓存 RagEtaReportOpToCache LPush: 操作类型:%s,报告id:%d,章节id:%d", source, reportId, reportChapterId))
+		if err != nil {
+			fmt.Println("RagEtaReportOpToCache LPush Err:" + err.Error())
+		}
+		return true
+	}
+	return false
+}

+ 4 - 2
controllers/llm/llm_http/request.go

@@ -22,12 +22,14 @@ type UserChatRecordReq struct {
 }
 
 type GenerateContentReq struct {
-	WechatArticleId int    `json:"WechatArticleId" description:"公众号Id"`
+	Source          int    `json:"Source" description:"来源,0:公众号文章,1:eta报告"`
+	WechatArticleId int    `json:"WechatArticleId" description:"公众号文章Id"`
 	Promote         string `json:"Promote" description:"提示词"`
 	LLMModel        string `json:"LLMModel"`
 }
 type SaveContentReq struct {
-	WechatArticleId int             `json:"WechatArticleId" description:"公众号Id"`
+	Source          int             `json:"Source" description:"来源,0:公众号文章,1:eta报告"`
+	WechatArticleId int             `json:"WechatArticleId" description:"公众号文章Id"`
 	Title           string          `json:"Title" description:"标题"`
 	Llm             string          `json:"LLM"`
 	Promote         json.RawMessage `json:"Promote" description:"提示词"`

+ 33 - 11
controllers/llm/promote_controller.go

@@ -62,19 +62,38 @@ func (pCtrl *PromoteController) GenerateContent() {
 		Role:     "user",
 		SendTime: userSendTime.Format(utils.FormatDateTime),
 	}
-	article, err := rag.GetArticleById(gcReq.WechatArticleId)
-	if err != nil {
-		br.Msg = "获取公众号内容失败"
-		br.ErrMsg = "获取公众号内容失败,Err:" + err.Error()
-		return
-	}
-	if article.TextContent == "" {
-		br.Msg = "暂不支持纯文本以外的内容生成"
-		br.ErrMsg = "暂不支持纯文本以外的内容生成"
-		return
+
+	switch gcReq.Source {
+	case 0:
+		article, err := rag.GetArticleById(gcReq.WechatArticleId)
+		if err != nil {
+			br.Msg = "获取公众号内容失败"
+			br.ErrMsg = "获取公众号内容失败,Err:" + err.Error()
+			return
+		}
+		if article.TextContent == "" {
+			br.Msg = "暂不支持纯文本以外的内容生成"
+			br.ErrMsg = "暂不支持纯文本以外的内容生成"
+			return
+		}
+	case 1:
+		obj := rag.RagEtaReport{}
+		article, err := obj.GetById(gcReq.WechatArticleId)
+		if err != nil {
+			br.Msg = "获取报告内容失败"
+			br.ErrMsg = "获取报告内容失败,Err:" + err.Error()
+			return
+		}
+		if article.TextContent == "" {
+			br.Msg = "暂不支持纯文本以外的内容生成"
+			br.ErrMsg = "暂不支持纯文本以外的内容生成"
+			return
+		}
+
 	}
 	res, err := facade.AIGCBaseOnPromote(facade.AIGC{
 		Promote:   gcReq.Promote,
+		Source:    gcReq.Source,
 		ArticleId: gcReq.WechatArticleId,
 		LLMModel:  gcReq.LLMModel,
 	})
@@ -95,6 +114,7 @@ func (pCtrl *PromoteController) GenerateContent() {
 	}
 	llm := strings.ReplaceAll(gcReq.LLMModel, ":", "")
 	saveContentReq := rag.PromoteTrainRecord{
+		Source:          gcReq.Source,
 		WechatArticleId: gcReq.WechatArticleId,
 		Title:           userContent.Content,
 		Llm:             llm,
@@ -200,6 +220,7 @@ func (pCtrl *PromoteController) SavePromoteContent() {
 	}
 	llm := strings.ReplaceAll(gcReq.Llm, ":", "")
 	saveContentReq := rag.PromoteTrainRecord{
+		Source:          gcReq.Source,
 		WechatArticleId: gcReq.WechatArticleId,
 		Title:           titile,
 		Llm:             llm,
@@ -273,6 +294,7 @@ func (pCtrl *PromoteController) PromoteContentList() {
 		pCtrl.ServeJSON()
 	}()
 	wechatArticleId, _ := pCtrl.GetInt("WechatArticleId")
+	source, _ := pCtrl.GetInt("Source")
 	sysUser := pCtrl.SysUser
 	if sysUser == nil {
 		br.Msg = "请登录"
@@ -287,7 +309,7 @@ func (pCtrl *PromoteController) PromoteContentList() {
 		return
 	}
 
-	list, err := rag.GetRecordList(wechatArticleId)
+	list, err := rag.GetRecordList(wechatArticleId, source)
 	if err != nil {
 		br.Msg = "查询列表失败"
 		br.ErrMsg = "查询列表失败,err:" + err.Error()

+ 249 - 0
controllers/llm/report.go

@@ -0,0 +1,249 @@
+package llm
+
+import (
+	"eta/eta_api/controllers"
+	"eta/eta_api/models"
+	"eta/eta_api/models/rag"
+	"eta/eta_api/models/rag/response"
+	"eta/eta_api/services"
+	"eta/eta_api/utils"
+	"fmt"
+	"github.com/rdlucklib/rdluck_tools/paging"
+	"html"
+	"strings"
+)
+
+// RagEtaReportController
+// @Description: eta报告的接口
+type RagEtaReportController struct {
+	controllers.BaseAuthController
+}
+
+// ArticleList
+// @Title 我关注的接口
+// @Description 我关注的接口
+// @Param   PageSize   query   int  true       "每页数据条数"
+// @Param   CurrentIndex   query   int  true       "当前页页码,从1开始"
+// @Param   KeyWord   query   string  true       "搜索关键词"
+// @Success 200 {object} *rag.RagEtaReportListListResp
+// @router /eta_report/article/list [get]
+func (c *RagEtaReportController) ArticleList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+
+	sysUser := c.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		return
+	}
+	pageSize, _ := c.GetInt("PageSize")
+	currentIndex, _ := c.GetInt("CurrentIndex")
+	keyWord := c.GetString("KeyWord")
+
+	var startSize int
+	if pageSize <= 0 {
+		pageSize = utils.PageSize20
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	startSize = utils.StartIndex(currentIndex, pageSize)
+
+	var total int
+	viewList := make([]rag.RagEtaReportView, 0)
+
+	var condition string
+	var pars []interface{}
+
+	condition += fmt.Sprintf(` AND %s = ? AND %s = ? `, rag.RagEtaReportColumns.IsDeleted, rag.RagEtaReportColumns.IsPublished)
+	pars = append(pars, 0, 1)
+
+	if keyWord != "" {
+		condition += fmt.Sprintf(` AND %s like ? `, rag.RagEtaReportColumns.Title)
+		pars = append(pars, `%`+keyWord+`%`)
+	}
+
+	obj := new(rag.RagEtaReport)
+	tmpTotal, list, err := obj.GetPageListByCondition(condition, pars, startSize, pageSize)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+	total = tmpTotal
+
+	if list != nil && len(list) > 0 {
+		viewList = obj.ListToViewList(list)
+	}
+
+	page := paging.GetPaging(currentIndex, pageSize, total)
+	resp := response.RagEtaReportListListResp{
+		List:   viewList,
+		Paging: page,
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+// ArticleDetail
+// @Title 文章详情
+// @Description 我关注的接口
+// @Param   RagEtaReportId   query   int  true       "知识库与eta报告关联的id"
+// @Success 200 {object} []*rag.WechatArticle
+// @router /eta_report/article/detail [get]
+func (c *RagEtaReportController) ArticleDetail() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+
+	sysUser := c.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		return
+	}
+	ragEtaReportId, _ := c.GetInt("RagEtaReportId")
+	if ragEtaReportId <= 0 {
+		br.Msg = "请选择文章"
+		br.IsSendEmail = false
+		return
+	}
+	obj := new(rag.RagEtaReport)
+	item, err := obj.GetById(ragEtaReportId)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+
+	if item.IsDeleted == 1 {
+		br.Msg = "文章已删除"
+		br.IsSendEmail = false
+		return
+	}
+	resp := item.ToView()
+
+	content := ``
+
+	// 获取源报告信息
+	{
+		if item.ReportChapterId <= 0 {
+			// 普通报告
+			reportInfo, err := models.GetReportByReportId(item.ReportId)
+			if err != nil && !utils.IsErrNoRow(err) {
+				br.Msg = "获取报告详情失败"
+				br.ErrMsg = "获取源报告详情失败,Err:" + err.Error()
+				return
+			}
+			content = reportInfo.Content
+			// 如果是rai报告,则使用纯文本的报告内容
+			if reportInfo.RaiReportId > 0 {
+				content = strings.ReplaceAll(item.TextContent, "\n", "<br />")
+			}
+		} else {
+			// 章节报告
+			reportChapterInfo, err := models.GetReportChapterInfoById(item.ReportChapterId)
+			if err != nil && !utils.IsErrNoRow(err) {
+				br.Msg = "获取报告详情失败"
+				br.ErrMsg = "获取源报告章节详情失败,Err:" + err.Error()
+				return
+			}
+			content = reportChapterInfo.Content
+		}
+
+		if content != `` {
+			content = html.UnescapeString(content)
+			businessConf, err := models.GetBusinessConfByKey(models.BusinessConfIsOpenChartExpired)
+			if err != nil {
+				br.Msg = "获取失败"
+				br.ErrMsg = "获取配置失败,Err:" + err.Error()
+				return
+			}
+
+			if businessConf.ConfVal == `true` {
+				tokenMap := make(map[string]string)
+				content = services.HandleReportContent(content, "add", tokenMap)
+			}
+		}
+	}
+
+	resp.Content = content
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+// ArticleDel
+// @Title 删除文章
+// @Description 我关注的接口
+// @Param   RagEtaReportId   query   int  true       "知识库与eta报告关联的id"
+// @Success 200 {object} []*rag.WechatPlatform
+// @router /eta_report/article/del [get]
+func (c *RagEtaReportController) ArticleDel() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+
+	sysUser := c.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		return
+	}
+	ragEtaReportId, _ := c.GetInt("RagEtaReportId")
+	if ragEtaReportId <= 0 {
+		br.Msg = "请选择文章"
+		br.IsSendEmail = false
+		return
+	}
+	obj := new(rag.RagEtaReport)
+	item, err := obj.GetById(ragEtaReportId)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+
+	if item.IsDeleted == 1 {
+		br.Msg = "文章已删除"
+		br.IsSendEmail = false
+		return
+	}
+	item.IsDeleted = 1
+	err = item.Update([]string{"is_deleted"})
+	if err != nil {
+		br.Msg = "删除失败"
+		br.ErrMsg = "删除失败,Err:" + err.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "删除成功"
+}
+
+//// 修复历史ETA报告到知识库
+//func init() {
+//	idList, err := models.GetAllPublishReportId()
+//	if err != nil {
+//		fmt.Println("查询失败:", err.Error())
+//		return
+//	}
+//	for _, v := range idList {
+//		cache.RagEtaReportOpToCache(v, 0, "publish")
+//	}
+//	fmt.Println("写入完成")
+//}

+ 7 - 0
controllers/report_v2.go

@@ -2,6 +2,7 @@ package controllers
 
 import (
 	"encoding/json"
+	"eta/eta_api/cache"
 	"eta/eta_api/models"
 	"eta/eta_api/models/report"
 	"eta/eta_api/models/report_approve"
@@ -1384,6 +1385,9 @@ func (this *ReportController) PublishCancelReport() {
 		_ = services.ResetMiniProgramReportDetailCover(reportInfo.Id)
 	}()
 
+	// 报告取消发布成功后,需要将相关信息入知识库
+	go cache.RagEtaReportOpToCache(reportInfo.Id, 0, `un_publish`)
+
 	br.Ret = 200
 	br.Success = true
 }
@@ -1717,6 +1721,9 @@ func (this *ReportController) CancelApprove() {
 		_ = services.ResetMiniProgramReportDetailCover(reportItem.Id)
 	}()
 
+	// 报告发布成功后,需要将相关信息入知识库
+	go cache.RagEtaReportOpToCache(reportItem.Id, 0, `un_publish`)
+
 	br.Ret = 200
 	br.Success = true
 	br.Msg = "操作成功"

+ 3 - 2
models/rag/article_kb_mapping.go

@@ -10,6 +10,7 @@ import (
 type ArticleKbMapping struct {
 	Id              int `gorm:"id;primaryKey"`
 	WechatArticleId int
+	Source          int
 	KbId            string
 	CreatedTime     time.Time
 	UpdateTime      time.Time
@@ -19,8 +20,8 @@ func (a *ArticleKbMapping) TableName() string {
 	return "article_kb_mapping"
 }
 
-func GetArticleKbMapping(articleId int) (articleKbMapping *ArticleKbMapping, err error) {
-	err = global.DbMap[utils.DbNameAI].Where("wechat_article_id = ?", articleId).First(&articleKbMapping).Error
+func GetArticleKbMapping(articleId, source int) (articleKbMapping *ArticleKbMapping, err error) {
+	err = global.DbMap[utils.DbNameAI].Where("wechat_article_id = ? AND source = ? ", articleId, source).First(&articleKbMapping).Error
 	return
 }
 

+ 5 - 2
models/rag/promote_train_record.go

@@ -10,6 +10,7 @@ type PromoteTrainRecord struct {
 	Id              int       `gorm:"id;primaryKey"`
 	Title           string    `gorm:"title"`
 	Llm             string    `gorm:"llm"`
+	Source          int       `gorm:"source" description:"来源,0:公众号文章,1:eta报告"`
 	WechatArticleId int       `gorm:"wechat_article_id"`
 	TemplatePromote string    `gorm:"template_promote"`
 	PromoteSendTime time.Time `gorm:"promote_send_time"`
@@ -25,6 +26,7 @@ func (p *PromoteTrainRecord) ToView() *PromoteTrainRecordView {
 		Id:              p.Id,
 		Title:           p.Title,
 		Llm:             p.Llm,
+		Source:          p.Source,
 		WechatArticleId: p.WechatArticleId,
 		TemplatePromote: p.TemplatePromote,
 		PromoteSendTime: p.PromoteSendTime.Format(utils.FormatDateTime),
@@ -37,6 +39,7 @@ type PromoteTrainRecordView struct {
 	Id              int
 	Title           string
 	Llm             string
+	Source          int
 	WechatArticleId int
 	TemplatePromote string
 	PromoteSendTime string
@@ -55,9 +58,9 @@ func DeleteContent(id int) error {
 	return global.DbMap[utils.DbNameAI].Model(&PromoteTrainRecord{}).Where("id = ?", id).Update("is_deleted", true).Error
 }
 
-func GetRecordList(wechatArticleId int) (list []*PromoteTrainRecordView, err error) {
+func GetRecordList(wechatArticleId, source int) (list []*PromoteTrainRecordView, err error) {
 	var ormList []PromoteTrainRecord
-	err = global.DbMap[utils.DbNameAI].Model(&PromoteTrainRecord{}).Where("wechat_article_id = ? and is_deleted=?", wechatArticleId, false).Order(`created_time DESC`).Find(&ormList).Error
+	err = global.DbMap[utils.DbNameAI].Model(&PromoteTrainRecord{}).Where("wechat_article_id = ? AND source = ?  and is_deleted=?", wechatArticleId, source, false).Order(`created_time DESC`).Find(&ormList).Error
 	if err != nil {
 		return
 	}

+ 168 - 0
models/rag/rag_eta_report.go

@@ -0,0 +1,168 @@
+package rag
+
+import (
+	"database/sql"
+	"eta/eta_api/global"
+	"eta/eta_api/utils"
+	"fmt"
+	"time"
+)
+
+// RagEtaReport eta报告
+type RagEtaReport struct {
+	RagEtaReportId  int       `gorm:"primaryKey;column:rag_eta_report_id" `
+	ReportId        int       `gorm:"column:report_id" description:"报告id"`
+	ReportChapterId int       `gorm:"column:report_chapter_id" description:"报告章节id"`
+	Title           string    `gorm:"column:title" description:"报告标题(完整标题,含期数)"`
+	Author          string    `gorm:"column:author" description:"作者"`
+	TextContent     string    `gorm:"column:text_content" description:"报告内容(去除html)"`
+	VectorKey       string    `gorm:"column:vector_key" description:"向量库的key"`
+	IsPublished     int       `gorm:"column:is_published;type:tinyint(4);comment:是否已发布,0:未发布,1:已发布;default:1;" description:"是否已发布,0:未发布,1:已发布"`
+	IsDeleted       int       `gorm:"column:is_deleted;type:tinyint(4);comment:是否删除,0:未删除,1:已删除;default:0;" description:"否删除,0:未删除,1:已删除"`
+	PublishTime     time.Time `gorm:"column:publish_time" description:"发布时间"`
+	ModifyTime      time.Time `gorm:"column:modify_time" description:"修改时间"`
+	CreateTime      time.Time `gorm:"column:create_time" description:"新增时间"`
+}
+
+// TableName get sql table name.获取数据库表名
+func (m *RagEtaReport) TableName() string {
+	return "rag_eta_report"
+}
+
+// RagEtaReportColumns get sql column name.获取数据库列名
+var RagEtaReportColumns = struct {
+	RagEtaReportID  string
+	ReportID        string
+	ReportChapterID string
+	Title           string
+	Author          string
+	TextContent     string
+	VectorKey       string
+	IsPublished     string
+	IsDeleted       string
+	PublishTime     string
+	ModifyTime      string
+	CreateTime      string
+}{
+	RagEtaReportID:  "rag_eta_report_id",
+	ReportID:        "report_id",
+	ReportChapterID: "report_chapter_id",
+	Title:           "title",
+	Author:          "author",
+	TextContent:     "text_content",
+	VectorKey:       "vector_key",
+	IsPublished:     "is_published",
+	IsDeleted:       "is_deleted",
+	PublishTime:     "publish_time",
+	ModifyTime:      "modify_time",
+	CreateTime:      "create_time",
+}
+
+type RagEtaReportView struct {
+	RagEtaReportId  int    `gorm:"primaryKey;column:rag_eta_report_id" `
+	ReportId        int    `gorm:"column:report_id" description:"报告id"`
+	ReportChapterId int    `gorm:"column:report_chapter_id" description:"报告章节id"`
+	Title           string `gorm:"column:title" description:"报告标题(完整标题,含期数)"`
+	Author          string `gorm:"column:author" description:"作者"`
+	Content         string `gorm:"column:content" description:"报告内容(包含html)"`
+	TextContent     string `gorm:"column:text_content" description:"报告内容(去除html)"`
+	VectorKey       string `gorm:"column:vector_key" description:"向量库的key"`
+	IsDeleted       int    `gorm:"column:is_deleted;type:tinyint(4);comment:是否删除,0:未删除,1:已删除;default:0;" description:"否删除,0:未删除,1:已删除"`
+	PublishTime     string `gorm:"column:publish_time" description:"发布时间"`
+	ModifyTime      string `gorm:"column:modify_time" description:"修改时间"`
+	CreateTime      string `gorm:"column:create_time" description:"新增时间"`
+}
+
+func (m *RagEtaReport) ToView() RagEtaReportView {
+	var publishTime, modifyTime, createTime string
+
+	if !m.PublishTime.IsZero() {
+		publishTime = m.PublishTime.Format(utils.FormatDateTime)
+	}
+	if !m.CreateTime.IsZero() {
+		createTime = m.CreateTime.Format(utils.FormatDateTime)
+	}
+	if !m.ModifyTime.IsZero() {
+		modifyTime = m.ModifyTime.Format(utils.FormatDateTime)
+	}
+	return RagEtaReportView{
+		RagEtaReportId:  m.RagEtaReportId,
+		ReportId:        m.ReportId,
+		ReportChapterId: m.ReportChapterId,
+		Title:           m.Title,
+		Author:          m.Author,
+		TextContent:     m.TextContent,
+		VectorKey:       m.VectorKey,
+		PublishTime:     publishTime,
+		ModifyTime:      modifyTime,
+		CreateTime:      createTime,
+	}
+}
+
+func (m *RagEtaReport) ListToViewList(list []*RagEtaReport) (RagEtaReportViewList []RagEtaReportView) {
+	RagEtaReportViewList = make([]RagEtaReportView, 0)
+
+	for _, v := range list {
+		RagEtaReportViewList = append(RagEtaReportViewList, v.ToView())
+	}
+	return
+}
+
+func (m *RagEtaReport) Create() (err error) {
+	err = global.DbMap[utils.DbNameAI].Create(&m).Error
+
+	return
+}
+
+func (m *RagEtaReport) Update(updateCols []string) (err error) {
+	err = global.DbMap[utils.DbNameAI].Select(updateCols).Updates(&m).Error
+
+	return
+}
+
+func (m *RagEtaReport) GetById(id int) (item *RagEtaReport, err error) {
+	err = global.DbMap[utils.DbNameAI].Where(fmt.Sprintf("%s = ?", RagEtaReportColumns.RagEtaReportID), id).First(&item).Error
+
+	return
+}
+
+func (m *RagEtaReport) GetByReportAndChapterId(reportId, reportChapterId int) (item *RagEtaReport, err error) {
+	err = global.DbMap[utils.DbNameAI].Where(fmt.Sprintf("%s = ? AND %s = ? ", RagEtaReportColumns.ReportID, RagEtaReportColumns.ReportChapterID), reportId, reportChapterId).First(&item).Error
+
+	return
+}
+
+func (m *RagEtaReport) GetListByCondition(field, condition string, pars []interface{}, startSize, pageSize int) (items []*RagEtaReport, err error) {
+	if field == "" {
+		field = "*"
+	}
+	sqlStr := fmt.Sprintf(`SELECT %s FROM %s WHERE is_deleted=0 %s  order by publish_time desc,report_id desc,report_chapter_id desc LIMIT ?,?`, field, m.TableName(), condition)
+	pars = append(pars, startSize, pageSize)
+	err = global.DbMap[utils.DbNameAI].Raw(sqlStr, pars...).Find(&items).Error
+
+	return
+}
+
+func (m *RagEtaReport) GetCountByCondition(condition string, pars []interface{}) (total int, err error) {
+	var intNull sql.NullInt64
+	sqlStr := fmt.Sprintf(`SELECT COUNT(1) total FROM %s WHERE 1=1 AND is_deleted=0 %s`, m.TableName(), condition)
+	err = global.DbMap[utils.DbNameAI].Raw(sqlStr, pars...).Scan(&intNull).Error
+	if err == nil && intNull.Valid {
+		total = int(intNull.Int64)
+	}
+
+	return
+}
+
+func (m *RagEtaReport) GetPageListByCondition(condition string, pars []interface{}, startSize, pageSize int) (total int, items []*RagEtaReport, err error) {
+
+	total, err = m.GetCountByCondition(condition, pars)
+	if err != nil {
+		return
+	}
+	if total > 0 {
+		items, err = m.GetListByCondition(``, condition, pars, startSize, pageSize)
+	}
+
+	return
+}

+ 11 - 0
models/rag/response/eta_report.go

@@ -0,0 +1,11 @@
+package response
+
+import (
+	"eta/eta_api/models/rag"
+	"github.com/rdlucklib/rdluck_tools/paging"
+)
+
+type RagEtaReportListListResp struct {
+	List   []rag.RagEtaReportView
+	Paging *paging.PagingItem `description:"分页数据"`
+}

+ 7 - 0
models/report.go

@@ -1693,3 +1693,10 @@ type ReportShartUrlReq struct {
 type ReportShartUrlResp struct {
 	UrlToken string `description:"分享链接token"`
 }
+
+func GetAllPublishReportId() (items []int, err error) {
+	o := global.DbMap[utils.DbNameReport]
+	sql := `SELECT  a.id FROM report as a WHERE 1=1 AND state in (2,6) `
+	err = o.Raw(sql).Find(&items).Error
+	return
+}

+ 27 - 0
routers/commentsRouter.go

@@ -8773,6 +8773,33 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["eta/eta_api/controllers/llm:RagEtaReportController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/llm:RagEtaReportController"],
+        beego.ControllerComments{
+            Method: "ArticleDel",
+            Router: `/eta_report/article/del`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/llm:RagEtaReportController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/llm:RagEtaReportController"],
+        beego.ControllerComments{
+            Method: "ArticleDetail",
+            Router: `/eta_report/article/detail`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/llm:RagEtaReportController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/llm:RagEtaReportController"],
+        beego.ControllerComments{
+            Method: "ArticleList",
+            Router: `/eta_report/article/list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["eta/eta_api/controllers/llm:UserChatController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/llm:UserChatController"],
         beego.ControllerComments{
             Method: "ChatRecordList",

+ 1 - 0
routers/router.go

@@ -79,6 +79,7 @@ func init() {
 				&llm.QuestionController{},
 				&llm.AbstractController{},
 				&llm.PromoteController{},
+				&llm.RagEtaReportController{},
 			),
 		),
 		web.NSNamespace("/banner",

+ 53 - 17
services/llm/facade/llm_service.go

@@ -53,7 +53,7 @@ func AIGCBaseOnPromote(aigc AIGC) (resp bus_response.AIGCEtaResponse, err error)
 	if aigc.LLMModel != "" {
 		param["LLM"] = aigc.LLMModel
 	}
-	mapping, queryErr := rag.GetArticleKbMapping(aigc.ArticleId)
+	mapping, queryErr := rag.GetArticleKbMapping(aigc.ArticleId, aigc.Source)
 	if queryErr != nil && !errors.Is(queryErr, gorm.ErrRecordNotFound) {
 		utils.FileLog.Error("获取文章知识库信息失败,err: %v", queryErr)
 		err = fmt.Errorf("获取文章知识库信息失败,err: %v", queryErr)
@@ -62,20 +62,37 @@ func AIGCBaseOnPromote(aigc AIGC) (resp bus_response.AIGCEtaResponse, err error)
 		var kbId string
 		var file *os.File
 		if mapping.Id == 0 || mapping.KbId == "" {
-			article, fileErr := rag.GetArticleById(aigc.ArticleId)
-			if fileErr != nil {
-				// 找不到就处理失败
-				utils.FileLog.Error("公众号文章不存在")
-				err = fmt.Errorf("公众号文章不存在")
-				return
+			var title, textContent string
+			switch aigc.Source {
+			case 0:
+				article, fileErr := rag.GetArticleById(aigc.ArticleId)
+				if fileErr != nil {
+					// 找不到就处理失败
+					utils.FileLog.Error("公众号文章不存在")
+					err = fmt.Errorf("公众号文章不存在")
+					return
+				}
+				textContent = article.TextContent
+				title = article.Title
+			case 1:
+				ragEtaReportObj := rag.RagEtaReport{}
+				article, fileErr := ragEtaReportObj.GetById(aigc.ArticleId)
+				if fileErr != nil {
+					// 找不到就处理失败
+					utils.FileLog.Error("ETA文章不存在")
+					err = fmt.Errorf("ETA文章不存在")
+					return
+				}
+				textContent = article.TextContent
+				title = article.Title
 			}
-			if article.TextContent == "" {
+			if textContent == "" {
 				utils.FileLog.Error("暂不支持纯文本以外的内容生成")
 				err = fmt.Errorf("暂不支持纯文本以外的内容生成")
 				return
 			}
 			// 文章加入到知识库
-			path, fileErr := localService.CreateArticleFile(article)
+			path, fileErr := localService.CreateArticleFile(title, textContent)
 			if fileErr != nil {
 				utils.FileLog.Error("创建文章文件失败,err: %v", fileErr)
 				err = fmt.Errorf("创建文章文件失败,err: %v", fileErr)
@@ -103,6 +120,7 @@ func AIGCBaseOnPromote(aigc AIGC) (resp bus_response.AIGCEtaResponse, err error)
 				return
 			}
 			err = rag.CreateArticleKbMapping(rag.ArticleKbMapping{
+				Source:          aigc.Source,
 				WechatArticleId: aigc.ArticleId,
 				KbId:            data.Id,
 				CreatedTime:     time.Now(),
@@ -134,20 +152,37 @@ func AIGCBaseOnPromote(aigc AIGC) (resp bus_response.AIGCEtaResponse, err error)
 		}
 		if gcResp.Code == 404 {
 			param["PrevId"] = kbId
-			article, fileErr := rag.GetArticleById(aigc.ArticleId)
-			if fileErr != nil {
-				// 找不到就处理失败
-				utils.FileLog.Error("公众号文章不存在")
-				err = fmt.Errorf("公众号文章不存在")
-				return
+			var title, textContent string
+			switch aigc.Source {
+			case 0:
+				article, fileErr := rag.GetArticleById(aigc.ArticleId)
+				if fileErr != nil {
+					// 找不到就处理失败
+					utils.FileLog.Error("公众号文章不存在")
+					err = fmt.Errorf("公众号文章不存在")
+					return
+				}
+				textContent = article.TextContent
+				title = article.Title
+			case 1:
+				ragEtaReportObj := rag.RagEtaReport{}
+				article, fileErr := ragEtaReportObj.GetById(aigc.ArticleId)
+				if fileErr != nil {
+					// 找不到就处理失败
+					utils.FileLog.Error("ETA文章不存在")
+					err = fmt.Errorf("ETA文章不存在")
+					return
+				}
+				textContent = article.TextContent
+				title = article.Title
 			}
-			if article.TextContent == "" {
+			if textContent == "" {
 				utils.FileLog.Error("暂不支持纯文本以外的内容生成")
 				err = fmt.Errorf("暂不支持纯文本以外的内容生成")
 				return
 			}
 			// 文章加入到知识库
-			path, fileErr := localService.CreateArticleFile(article)
+			path, fileErr := localService.CreateArticleFile(title, textContent)
 			if fileErr != nil {
 				utils.FileLog.Error("创建文章文件失败,err: %v", fileErr)
 				err = fmt.Errorf("创建文章文件失败,err: %v", fileErr)
@@ -202,6 +237,7 @@ type LLMKnowledgeSearch struct {
 
 type AIGC struct {
 	Promote   string
+	Source    int
 	ArticleId int
 	LLMModel  string
 }

+ 4 - 5
services/llm/promote_service.go

@@ -1,14 +1,13 @@
 package llm
 
 import (
-	"eta/eta_api/models/rag"
 	"eta/eta_api/utils"
 	"fmt"
 	"os"
 )
 
-func CreateArticleFile(item *rag.WechatArticle) (tmpFilePath string, err error) {
-	if item.TextContent == `` {
+func CreateArticleFile(title, textContent string) (tmpFilePath string, err error) {
+	if textContent == `` {
 		err = fmt.Errorf("生成文章原文文本失败,文章内容为空")
 		return
 	}
@@ -19,9 +18,9 @@ func CreateArticleFile(item *rag.WechatArticle) (tmpFilePath string, err error)
 		err = fmt.Errorf("存储目录创建失败,Err:" + err.Error())
 		return
 	}
-	fileName := utils.RemoveSpecialChars(item.Title) + `.md`
+	fileName := utils.RemoveSpecialChars(title) + `.md`
 	tmpFilePath = uploadDir + "/" + fileName
-	err = utils.SaveToFile(item.TextContent, tmpFilePath)
+	err = utils.SaveToFile(textContent, tmpFilePath)
 	if err != nil {
 		err = fmt.Errorf("生成临时文件失败,Err:" + err.Error())
 		return

+ 272 - 0
services/llm_report.go

@@ -0,0 +1,272 @@
+package services
+
+import (
+	"eta/eta_api/models"
+	"eta/eta_api/models/rag"
+	"eta/eta_api/utils"
+	"fmt"
+	"golang.org/x/net/html"
+	"golang.org/x/net/html/atom"
+	"regexp"
+	"strings"
+	"time"
+)
+
+// ReportAddOrModifyKnowledge
+// @Description: ETA报告加入/修改到知识库
+// @author: Roc
+// @datetime 2025-04-07 14:41:45
+// @param reportId int
+// @param reportChapterId int
+func ReportAddOrModifyKnowledge(reportId, reportChapterId int) {
+	if reportId <= 0 {
+		return
+	}
+	var err error
+	defer func() {
+		if err != nil {
+			//fmt.Println("ReportAddOrModifyKnowledge error:", err)
+			utils.FileLog.Error("ReportAddOrModifyKnowledge error:", err)
+		}
+	}()
+
+	var title, author, htmlContent string
+	var publishTime time.Time
+
+	if reportChapterId > 0 {
+		chapterInfo, tmpErr := models.GetReportChapterInfoById(reportChapterId)
+		if tmpErr != nil {
+			return
+		}
+		title = chapterInfo.Title
+		author = chapterInfo.Author
+		publishTime = chapterInfo.PublishTime
+		htmlContent = chapterInfo.Content
+	} else {
+		reportInfo, tmpErr := models.GetReportByReportId(reportId)
+		if tmpErr != nil {
+			return
+		}
+		title = reportInfo.Title
+		author = reportInfo.Author
+		publishTime = reportInfo.PublishTime
+		htmlContent = reportInfo.Content
+	}
+
+	err = handleReportAddOrModifyKnowledge(reportId, reportChapterId, title, author, htmlContent, publishTime)
+
+	return
+}
+
+// ReportAddOrModifyKnowledgeByReportId
+// @Description: ETA报告加入/修改到知识库(只传id的情况)
+// @author: Roc
+// @datetime 2025-04-07 15:41:15
+// @param reportId int
+func ReportAddOrModifyKnowledgeByReportId(reportId int) {
+	if reportId <= 0 {
+		return
+	}
+	errList := make([]string, 0)
+	defer func() {
+		if len(errList) > 0 {
+			utils.FileLog.Error("ReportAddOrModifyKnowledge error,报告ID:%d:%s", reportId, strings.Join(errList, "\n"))
+		}
+	}()
+
+	reportInfo, err := models.GetReportByReportId(reportId)
+	if err != nil {
+		errList = append(errList, err.Error())
+		return
+	}
+
+	// 如果是单篇报告,那么直接处理
+	if reportInfo.HasChapter == 0 {
+		err = handleReportAddOrModifyKnowledge(reportId, 0, reportInfo.Title, reportInfo.Author, reportInfo.Content, reportInfo.PublishTime)
+		if err != nil {
+			errList = append(errList, err.Error())
+		}
+		return
+	}
+
+	// 章节类型的报告,需要查询出来后再处理
+	chapterInfoList, err := models.GetPublishedChapterListByReportId(reportId)
+	if err != nil {
+		errList = append(errList, err.Error())
+		return
+	}
+	for _, v := range chapterInfoList {
+		err = handleReportAddOrModifyKnowledge(reportId, v.ReportChapterId, v.Title, reportInfo.Author, v.Content, v.PublishTime)
+		if err != nil {
+			errList = append(errList, fmt.Sprintf("第%d章:%s,异常:\n%s", v.ReportChapterId, v.Title, err.Error()))
+			continue
+		}
+	}
+
+	return
+}
+
+// handleReportAddOrModifyKnowledge
+// @Description: 处理ETA报告加入/修改到知识库
+// @author: Roc
+// @datetime 2025-04-07 15:33:38
+// @param reportId int
+// @param reportChapterId int
+// @param title string
+// @param author string
+// @param htmlContent string
+// @param publishTime time.Time
+// @return err error
+func handleReportAddOrModifyKnowledge(reportId, reportChapterId int, title, author, htmlContent string, publishTime time.Time) (err error) {
+	htmlContent = html.UnescapeString(htmlContent)
+	doc, err := html.Parse(strings.NewReader(htmlContent))
+	if err != nil {
+		return
+	}
+	// 只获取文本内容
+	content := &strings.Builder{}
+	getArticleContent(content, doc)
+
+	textContent := content.String()
+	textContent = regexp.MustCompile(`\n+`).ReplaceAllString(textContent, "\n")
+	textContent = strings.Trim(textContent, "\n")
+
+	publishTimeStr := `未知`
+	if !publishTime.IsZero() {
+		title = fmt.Sprintf("%s(%s)", title, publishTime.Format(utils.FormatMonthDayUnSpace))
+		publishTimeStr = publishTime.Format(utils.FormatDateTime)
+	}
+
+	textContent = fmt.Sprintf("标题:%s\n发布时间:%s\n%s", title, publishTimeStr, textContent)
+
+	obj := rag.RagEtaReport{}
+	item, err := obj.GetByReportAndChapterId(reportId, reportChapterId)
+	if err != nil && !utils.IsErrNoRow(err) {
+		// 查询异常,且不是没找到数据的报错
+		return
+	}
+
+	if err == nil {
+		// 标记删除了的话,那就不处理了
+		if item.IsDeleted == 1 {
+			return
+		}
+		item.Title = title
+		item.Author = author
+		item.TextContent = textContent
+		item.IsPublished = 1
+		//item.PublishTime = publishTime
+		item.ModifyTime = time.Now()
+		//err = item.Update([]string{"title", "author", "text_content", "is_published", "publish_time", "modify_time"})
+		err = item.Update([]string{"title", "author", "text_content", "is_published", "modify_time"})
+	} else {
+		// 无数据的时候,需要新增
+		err = nil
+		item = &rag.RagEtaReport{
+			RagEtaReportId:  0,
+			ReportId:        reportId,
+			ReportChapterId: reportChapterId,
+			Title:           title,
+			Author:          author,
+			TextContent:     textContent,
+			VectorKey:       "",
+			IsPublished:     1,
+			IsDeleted:       0,
+			PublishTime:     publishTime,
+			ModifyTime:      time.Now(),
+			CreateTime:      time.Now(),
+		}
+		err = item.Create()
+	}
+
+	return
+}
+
+// ReportUnPublishedKnowledge
+// @Description: 知识库取消发布
+// @author: Roc
+// @datetime 2025-04-07 14:58:25
+// @param reportId int
+// @param reportChapterId int
+func ReportUnPublishedKnowledge(reportId, reportChapterId int) {
+	if reportId <= 0 && reportChapterId <= 0 {
+		return
+	}
+	var err error
+	defer func() {
+		if err != nil {
+			//fmt.Println("ReportAddOrModifyKnowledge error:", err)
+			utils.FileLog.Error("ReportAddOrModifyKnowledge error:", err)
+		}
+	}()
+
+	obj := rag.RagEtaReport{}
+	item, err := obj.GetByReportAndChapterId(reportId, reportChapterId)
+	if err != nil && !utils.IsErrNoRow(err) {
+		// 查询异常,且不是没找到数据的报错
+		return
+	}
+
+	if item.RagEtaReportId > 0 {
+		item.IsPublished = 0
+		item.ModifyTime = time.Now()
+		err = item.Update([]string{"is_published", "modify_time"})
+	}
+
+	return
+}
+
+// ReportUnPublishedKnowledgeByReportId
+// @Description: ETA报告取消发布同步到知识库(只传报告id的情况)
+// @author: Roc
+// @datetime 2025-04-07 15:41:15
+// @param reportId int
+func ReportUnPublishedKnowledgeByReportId(reportId int) {
+	errList := make([]string, 0)
+	defer func() {
+		if len(errList) > 0 {
+			utils.FileLog.Error("ReportUnPublishedKnowledgeByReportId error,报告ID:%d:%s", reportId, strings.Join(errList, "\n"))
+		}
+	}()
+
+	obj := rag.RagEtaReport{}
+	list, err := obj.GetListByCondition(``, ` AND report_id = ? `, []interface{}{reportId}, 0, 1000)
+	if err != nil && !utils.IsErrNoRow(err) {
+		// 查询异常,且不是没找到数据的报错
+		return
+	}
+
+	for _, item := range list {
+		item.IsPublished = 0
+		item.ModifyTime = time.Now()
+		err = item.Update([]string{"is_published", "modify_time"})
+		if err != nil {
+			errList = append(errList, fmt.Sprintf("第%d章:%s,异常:\n%s", item.ReportChapterId, item.Title, err.Error()))
+			continue
+		}
+	}
+
+	return
+}
+
+func getArticleContent(content *strings.Builder, htmlContentNode *html.Node) {
+	if htmlContentNode.Type == html.TextNode {
+		cleanData := strings.TrimSpace(htmlContentNode.Data)
+		if cleanData != `` && cleanData != "</p>" {
+			content.WriteString(cleanData)
+		}
+	} else if htmlContentNode.Type == html.ElementNode {
+		switch htmlContentNode.DataAtom {
+		case atom.Ul:
+			content.WriteString("\n")
+		case atom.Br:
+			// 遇到 <br> 标签时添加换行符
+			content.WriteString("\n")
+		case atom.P:
+			content.WriteString("\n")
+		}
+	}
+	for c := htmlContentNode.FirstChild; c != nil; c = c.NextSibling {
+		getArticleContent(content, c)
+	}
+}

+ 4 - 0
services/report_approve.go

@@ -1,6 +1,7 @@
 package services
 
 import (
+	"eta/eta_api/cache"
 	"eta/eta_api/models"
 	"eta/eta_api/models/report_approve"
 	"eta/eta_api/models/smart_report"
@@ -867,6 +868,9 @@ func AfterReportApprovePass(reportType, reportId int) (err error) {
 		//_ = CreateVideo(reportInfo)
 		_ = UpdateReportEs(reportInfo.Id, models.ReportStatePublished)
 
+		// 报告发布成功后,需要将相关信息入知识库
+		go cache.RagEtaReportOpToCache(reportInfo.Id, 0, `publish`)
+
 		return
 	}
 

+ 31 - 20
services/report_rai.go

@@ -2,6 +2,7 @@ package services
 
 import (
 	"encoding/json"
+	"eta/eta_api/cache"
 	"eta/eta_api/models"
 	"eta/eta_api/models/report"
 	"eta/eta_api/services/alarm_msg"
@@ -47,7 +48,7 @@ func HandleInsertRaiReport(raiReportId int) (err error) {
 	if err != nil {
 		fmt.Println(err)
 		err = fmt.Errorf("获取权益报告失败, Err: %s", err.Error())
-		return 
+		return
 	}
 	var articleResultDate models.ArticleDetailResultApi
 	err = json.Unmarshal(body, &articleResultDate)
@@ -55,7 +56,7 @@ func HandleInsertRaiReport(raiReportId int) (err error) {
 		fmt.Println("Getres.PublicGetDate Err:", err.Error())
 		return err
 	}
-	
+
 	articleResult := articleResultDate.Data
 	err = handleInsertRaiReport(articleResult)
 	if err != nil {
@@ -90,7 +91,7 @@ func handleInsertRaiReport(articleResult models.ArticleResultApidate) (err error
 	// if err != nil {
 	// 	fmt.Println(err)
 	// 	err = fmt.Errorf("获取权益报告失败, Err: %s", err.Error())
-	// 	return 
+	// 	return
 	// }
 	// var articleResultDate models.ArticleDetailResultApi
 	// err = json.Unmarshal(body, &articleResultDate)
@@ -98,7 +99,7 @@ func handleInsertRaiReport(articleResult models.ArticleResultApidate) (err error
 	// 	fmt.Println("Getres.PublicGetDate Err:", err.Error())
 	// 	return err
 	// }
-	
+
 	// articleResult := articleResultDate.Data
 	// 判断是否是固收研究
 	if articleResult.IndustrId != 12 {
@@ -154,12 +155,16 @@ func handleInsertRaiReport(articleResult models.ArticleResultApidate) (err error
 		}
 		state := reportInfo.State
 
+		publishSource := `publish` //同步至知识库
+
 		// 报告已存在,更新报告
 		if (articleResult.PublishStatus == 2 || articleResult.PublishStatus == 4) && articleResult.IsActive {
 			// 报告状态为未发布,则更新报告
 			state = models.ReportStatePublished
 			reportInfo.PublishTime = articleResult.PublishDate
-		}else if !articleResult.IsActive {
+		} else if !articleResult.IsActive {
+			publishSource = `un_publish` //同步至知识库
+
 			// 删除报告
 			err = models.DeleteReport(reportInfo.Id)
 			if err != nil {
@@ -168,11 +173,12 @@ func handleInsertRaiReport(articleResult models.ArticleResultApidate) (err error
 			}
 			go UpdateReportEs(reportInfo.Id, 1)
 			return
-		}else {
+		} else {
+			publishSource = `un_publish` //同步至知识库
+
 			// 报告状态为未发布,则更新报告
 			state = models.ReportStateUnpublished
 			reportInfo.PublishTime = articleResult.PublishDate
-			
 		}
 		// 过滤Abstracthtml标签,把<p>标签去掉
 		abstract := strings.ReplaceAll(articleResult.Content.Abstract, "<p>", "")
@@ -193,7 +199,7 @@ func handleInsertRaiReport(articleResult models.ArticleResultApidate) (err error
 		reportInfo.ModifyTime = articleResult.UpdateDate
 
 		// 报告更新
-		updateCols := []string{"ClassifyIdFirst","ClassifyNameFirst","ClassifyIdSecond","ClassifyNameSecond","Title","Abstract","Author","Frequency","State","Content","ContentSub","ModifyTime","PublishTime"}
+		updateCols := []string{"ClassifyIdFirst", "ClassifyNameFirst", "ClassifyIdSecond", "ClassifyNameSecond", "Title", "Abstract", "Author", "Frequency", "State", "Content", "ContentSub", "ModifyTime", "PublishTime"}
 		err = reportInfo.UpdateReport(updateCols)
 		if err != nil {
 			err = fmt.Errorf("更新报告失败, Err: %s", err.Error())
@@ -203,12 +209,15 @@ func handleInsertRaiReport(articleResult models.ArticleResultApidate) (err error
 		if state == models.ReportStatePublished {
 			// 报告权限处理
 			go handleReportPermission(int64(reportInfo.Id), reportInfo.ClassifyIdSecond)
-		}else {
+		} else {
 			// 重置小程序详情页海报
 			_ = ResetMiniProgramReportDetailCover(reportInfo.Id)
 		}
 
-	}else if reportInfo.Id == 0 {
+		// 报告发布成功后,需要将相关信息入知识库
+		go cache.RagEtaReportOpToCache(reportInfo.Id, 0, publishSource)
+
+	} else if reportInfo.Id == 0 {
 		err = nil
 		// 报告不存在,创建报告
 		// 判断状态
@@ -222,22 +231,22 @@ func handleInsertRaiReport(articleResult models.ArticleResultApidate) (err error
 			}
 
 			// 已发布状态
-			state :=  models.ReportStatePublished
+			state := models.ReportStatePublished
 
 			// 协作方式,1:个人,2:多人协作。默认:1
 			collaborateType := 1
-	
+
 			// 报告布局,1:常规布局,2:智能布局。默认:1
 			reportLayout := 1
-	
+
 			// 是否公开发布,1:是,2:否
 			isPublicPublish := 1
-	
+
 			abstract := strings.ReplaceAll(articleResult.Content.Abstract, "<p>", "")
 			abstract = strings.ReplaceAll(abstract, "</p>", "")
 
 			item := new(models.Report)
-			item.AddType = 	1
+			item.AddType = 1
 			item.ReportVersion = 2
 			item.ClassifyIdFirst = classifyFirst.Id
 			item.ClassifyNameFirst = articleResult.Industry.Name
@@ -294,12 +303,14 @@ func handleInsertRaiReport(articleResult models.ArticleResultApidate) (err error
 				go models.ModifyReportCode(reportId, reportCode)
 			}
 
-
 			// 报告权限处理
 			go handleReportPermission(reportId, item.ClassifyIdSecond)
 
 			// 更新报告Es
 			_ = UpdateReportEs(int(reportId), 2)
+
+			// 报告发布成功后,需要将相关信息入知识库
+			go cache.RagEtaReportOpToCache(int(reportId), 0, `publish`)
 		}
 	}
 
@@ -333,7 +344,7 @@ func getRaiReportLib(url string) (body []byte, err error) {
 		return
 	}
 	defer res.Body.Close()
-	body, err = ioutil.ReadAll(res.Body) 
+	body, err = ioutil.ReadAll(res.Body)
 	if err != nil {
 		return
 	}
@@ -356,11 +367,11 @@ func RaiReportInit() (err error) {
 	successCount := 0
 	failCount := 0
 	for i := 0; i <= totalPage; i++ {
-		pageindex := i*pageSize 
+		pageindex := i * pageSize
 		body, er := getRaiReportLib(fmt.Sprintf("%s/articles/mp?take=%d&skip=%d&publish_status=2&industry_id=12", utils.RaiReportLibUrl, pageSize, pageindex))
 		if er != nil {
 			err = fmt.Errorf("获取权益报告失败, Err: %s", er.Error())
-			return 
+			return
 		}
 		// 解析内容,获取真实的分页总数
 		var articleResultDate models.RaiArticleListResultApi
@@ -381,7 +392,7 @@ func RaiReportInit() (err error) {
 				fmt.Printf("导入固收研究的历史报告失败%d, Err: %s\n", articleResult.ArticleId, err.Error())
 				failCount++
 				continue
-			}else {
+			} else {
 				fmt.Printf("导入固收研究的历史报告成功%d\n", articleResult.ArticleId)
 				successCount++
 			}

+ 7 - 0
services/report_v2.go

@@ -4,6 +4,7 @@ import (
 	"archive/zip"
 	"encoding/json"
 	"errors"
+	"eta/eta_api/cache"
 	"eta/eta_api/models"
 	"eta/eta_api/models/company"
 	"eta/eta_api/models/data_manage/excel"
@@ -1259,6 +1260,9 @@ func PublishReport(reportId int, reportUrl string, sysUser *system.Admin) (tips
 		go handleReportPermission(int64(reportInfo.Id), minClassifyId)
 	}
 
+	// 报告发布成功后,需要将相关信息入知识库
+	go cache.RagEtaReportOpToCache(reportInfo.Id, 0, `publish`)
+
 	return
 }
 
@@ -1377,6 +1381,9 @@ func PublishChapterReport(reportInfo *models.Report, reportUrl string, sysUser *
 		go Report2pdfAndJpeg(reportPdfUrl, reportId, 1)
 	}
 
+	// 报告发布成功后,需要将相关信息入知识库
+	go cache.RagEtaReportOpToCache(reportInfo.Id, 0, `publish`)
+
 	return
 }
 

+ 29 - 0
services/task.go

@@ -74,6 +74,9 @@ func Task() {
 	// 定时任务进行微信文章LLM操作
 	go HandleWechatArticleLLmOp()
 
+	// 队列任务将eta报告同步到知识库操作
+	go HandleEtaReportKnowledgeLLmOp()
+
 	// 权益报告监听入库
 	go AutoInsertRaiReport()
 
@@ -648,3 +651,29 @@ func HandleWechatArticleLLmOp() {
 		})
 	}
 }
+
+// HandleEtaReportKnowledgeLLmOp
+// @Description: 处理eta报告加入知识库操作
+func HandleEtaReportKnowledgeLLmOp() {
+	defer func() {
+		if err := recover(); err != nil {
+			fmt.Println("[HandleEtaReportKnowledgeLLmOp]", err)
+		}
+	}()
+	for {
+		utils.Rc.Brpop(utils.CACHE_ETA_REPORT_KNOWLEDGE, func(b []byte) {
+			ragEtaReportOpOp := new(cache.RagEtaReportOpOp)
+			if err := json.Unmarshal(b, &ragEtaReportOpOp); err != nil {
+				fmt.Println("json unmarshal wrong!")
+				return
+			}
+			switch ragEtaReportOpOp.Source {
+			case `publish`:
+				ReportAddOrModifyKnowledgeByReportId(ragEtaReportOpOp.ReportId)
+			case `un_publish`:
+				ReportUnPublishedKnowledgeByReportId(ragEtaReportOpOp.ReportId)
+			}
+
+		})
+	}
+}

+ 10 - 9
utils/constants.go

@@ -264,12 +264,13 @@ const (
 
 	CACHE_DATA_SOURCE_ES_HANDLE = "eta:data_source_es:handle" // 数据源es处理队列
 
-	CACHE_EXCEL_REFRESH                     = "CACHE_EXCEL_REFRESH"                  // 表格刷新
-	CACHE_WECHAT_PLATFORM_ARTICLE           = "wechat_platform:article:op"           //微信文章处理
-	CACHE_WECHAT_PLATFORM_ARTICLE_KNOWLEDGE = "wechat_platform:article:knowledge:op" //微信文章入知识库处理
-	CACHE_CHART_AUTH        = "eta:chart:auth:"        //图表数据授权
-	CACHE_REPORT_SHARE_AUTH = "eta:report:auth:share:" //报告短链与报告图表授权映射key
-	CACHE_REPORT_AUTH       = "eta:report:auth:"       //报告图表数据授权
+	CACHE_EXCEL_REFRESH                     = "CACHE_EXCEL_REFRESH"                   // 表格刷新
+	CACHE_WECHAT_PLATFORM_ARTICLE           = "wechat_platform:article:op:"           //微信文章处理
+	CACHE_WECHAT_PLATFORM_ARTICLE_KNOWLEDGE = "wechat_platform:article:knowledge:op:" //微信文章入知识库处理
+	CACHE_ETA_REPORT_KNOWLEDGE              = "eta:report:knowledge:op:"              //eta报告入知识库处理
+	CACHE_CHART_AUTH                        = "eta:chart:auth:"                       //图表数据授权
+	CACHE_REPORT_SHARE_AUTH                 = "eta:report:auth:share:"                //报告短链与报告图表授权映射key
+	CACHE_REPORT_AUTH                       = "eta:report:auth:"                      //报告图表数据授权
 )
 
 // 模板消息推送类型
@@ -584,9 +585,9 @@ const (
 )
 // 图表分类设置精选资源分类
 const (
-	ChartClassifyIsSelected = 1 // 图表分类设置精选资源分类
-	ChartClassifyResourceStatusUp = 1 // 图表分类上架状态
-	ChartClassifyResourceStatusDown = 2 // 图表分类下架状态
+	ChartClassifyIsSelected            = 1 // 图表分类设置精选资源分类
+	ChartClassifyResourceStatusUp      = 1 // 图表分类上架状态
+	ChartClassifyResourceStatusDown    = 2 // 图表分类下架状态
 	ChartClassifyResourceStatusDefault = 0 // 图表分类默认状态
 )