kobe6258 3 долоо хоног өмнө
parent
commit
53d736dcfa

+ 48 - 5
controllers/report_chapter.go

@@ -13,6 +13,7 @@ import (
 	"path"
 	"strconv"
 	"strings"
+	"sync"
 	"time"
 )
 
@@ -431,11 +432,53 @@ func (this *ReportController) EditDayWeekChapter() {
 			})
 		}
 	}
-	err = models.UpdateChapterAndTicker(reportInfo, reportChapterInfo, updateCols, tickerList)
-	if err != nil {
-		br.Msg = "保存失败"
-		br.ErrMsg = "报告章节内容保存失败, Err: " + err.Error()
-		return
+	if reportInfo.ReportLayout == 3 {
+		//对自由布局的数据做一个处理
+		//自由布局更新每页的数据
+		ormList := report.ToOrmViewList(req.FreeLayoutContentPages, false, reportInfo.Id, 0)
+		var wg sync.WaitGroup
+		wg.Add(len(ormList))
+		for _, v := range ormList {
+			go func(v *report.ReportFreeLayout) {
+				defer wg.Done()
+				content := v.Content
+				if content != "" {
+					e := utils.ContentXssCheck(content)
+					if e != nil {
+						br.Msg = "存在非法标签"
+						br.ErrMsg = "存在非法标签, Err: " + e.Error()
+						return
+					}
+					contentClean, e := services.FilterReportContentBr(content)
+					if e != nil {
+						br.Msg = "内容去除前后空格失败"
+						br.ErrMsg = "内容去除前后空格失败, Err: " + e.Error()
+						return
+					}
+					content = contentClean
+					if v.ContentStruct != `` {
+						v.ContentStruct = services.HandleReportContentStructTable(reportChapterInfo.ReportId, req.ContentStruct)
+						v.ContentStruct = services.HandleReportContentStruct(req.ContentStruct, "del", nil)
+					}
+					v.Content = html.EscapeString(content)
+					v.ContentStruct = html.EscapeString(v.ContentStruct)
+				}
+			}(v)
+			wg.Wait()
+			err = models.UpdateChapterFreeLayoutContentPage(reportInfo, reportChapterInfo, updateCols, tickerList, ormList)
+			if err != nil {
+				br.Msg = "保存失败"
+				br.ErrMsg = "保存失败,Err:" + err.Error()
+				return
+			}
+		}
+	} else {
+		err = models.UpdateChapterAndTicker(reportInfo, reportChapterInfo, updateCols, tickerList)
+		if err != nil {
+			br.Msg = "保存失败"
+			br.ErrMsg = "报告章节内容保存失败, Err: " + err.Error()
+			return
+		}
 	}
 
 	// 标记更新中

+ 86 - 33
controllers/report_v2.go

@@ -17,6 +17,7 @@ import (
 	"os"
 	"strconv"
 	"strings"
+	"sync"
 	"time"
 
 	"github.com/rdlucklib/rdluck_tools/paging"
@@ -795,7 +796,12 @@ func (this *ReportController) SaveReportContent() {
 		br.IsSendEmail = false
 		return
 	}
-
+	if reportInfo.ReportLayout == 3 && req.FreeLayoutConfig == "" {
+		br.Msg = "自由布局配置为空"
+		br.ErrMsg = "自由布局配置为空"
+		br.IsSendEmail = false
+		return
+	}
 	// 标记更新中
 	{
 		markStatus, err := services.UpdateReportEditMark(req.ReportId, 0, sysUser.AdminId, 1, sysUser.RealName, this.Lang)
@@ -838,6 +844,7 @@ func (this *ReportController) SaveReportContent() {
 				go alarm_msg.SendAlarmMsg("解析 ContentSub 失败,Err:"+err.Error(), 3)
 				//utils.SendEmail(utils.APPNAME+"失败提醒", "解析 ContentSub 失败,Err:"+err.Error(), utils.EmailSendToUsers)
 			}
+
 			reportInfo.Content = html.EscapeString(content)
 			reportInfo.ContentSub = html.EscapeString(contentSub)
 			reportInfo.ContentStruct = html.EscapeString(req.ContentStruct)
@@ -848,15 +855,56 @@ func (this *ReportController) SaveReportContent() {
 			reportInfo.EndResourceId = req.EndResourceId
 			reportInfo.ModifyTime = time.Now()
 			reportInfo.ContentModifyTime = time.Now()
-			updateCols := []string{"Content", "ContentSub", "ContentStruct", "HeadImg", "EndImg", "CanvasColor", "HeadResourceId", "EndResourceId", "ModifyTime", "ContentModifyTime"}
-			err = reportInfo.UpdateReport(updateCols)
-			if err != nil {
-				br.Msg = "保存失败"
-				br.ErrMsg = "保存失败,Err:" + err.Error()
-				return
+			if reportInfo.ReportLayout == 3 {
+				reportInfo.FreeLayoutConfig = req.FreeLayoutConfig
+				//自由布局更新每页的数据
+				ormList := report.ToOrmViewList(req.FreeLayoutContentPages, false, reportInfo.Id, 0)
+				var wg sync.WaitGroup
+				wg.Add(len(ormList))
+				for _, v := range ormList {
+					go func(v *report.ReportFreeLayout) {
+						defer wg.Done()
+						content = v.Content
+						if content != "" {
+							e = utils.ContentXssCheck(content)
+							if e != nil {
+								br.Msg = "存在非法标签"
+								br.ErrMsg = "存在非法标签, Err: " + e.Error()
+								return
+							}
+							contentClean, e = services.FilterReportContentBr(content)
+							if e != nil {
+								br.Msg = "内容去除前后空格失败"
+								br.ErrMsg = "内容去除前后空格失败, Err: " + e.Error()
+								return
+							}
+							content = contentClean
+							v.ContentStruct = services.HandleReportContentStruct(req.ContentStruct, "del", nil)
+							v.Content = html.EscapeString(content)
+							v.ContentStruct = html.EscapeString(v.ContentStruct)
+						}
+					}(v)
+					wg.Wait()
+					err = models.InsertOrUpdateReportFreeLayoutContentPage(reportInfo, ormList)
+					if err != nil {
+						br.Msg = "保存失败"
+						br.ErrMsg = "保存失败,Err:" + err.Error()
+						return
+					}
+				}
+			} else {
+				updateCols := []string{"Content", "ContentSub", "ContentStruct", "HeadImg", "EndImg", "CanvasColor", "HeadResourceId", "EndResourceId", "ModifyTime", "ContentModifyTime"}
+				err = reportInfo.UpdateReport(updateCols)
+				if err != nil {
+					br.Msg = "保存失败"
+					br.ErrMsg = "保存失败,Err:" + err.Error()
+					return
+				}
 			}
+
 			go models.AddReportSaveLog(reportId, this.SysUser.AdminId, reportInfo.Content, reportInfo.ContentSub, reportInfo.ContentStruct, reportInfo.CanvasColor, this.SysUser.AdminName, reportInfo.HeadResourceId, reportInfo.EndResourceId)
 		}
+
 	}
 
 	resp := new(models.SaveReportContentResp)
@@ -1022,17 +1070,21 @@ func (this *ReportController) BaseDetail() {
 		this.Data["json"] = br
 		this.ServeJSON()
 	}()
-	/*var req models.ReportDetailReq
-	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
-	if err != nil {
-		br.Msg = "参数解析异常!"
-		br.ErrMsg = "参数解析失败,Err:" + err.Error()
-		return
-	}
-	if req.ReportId <= 0 {
-		br.Msg = "参数错误"
-		return
-	}*/
+	/*
+	   var req models.ReportDetailReq
+	   err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+
+	   	if err != nil {
+	   		br.Msg = "参数解析异常!"
+	   		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+	   		return
+	   	}
+
+	   	if req.ReportId <= 0 {
+	   		br.Msg = "参数错误"
+	   		return
+	   	}
+	*/
 	reportId, err := this.GetInt("ReportId")
 	if err != nil {
 		br.Msg = "获取参数失败!"
@@ -1177,11 +1229,12 @@ func (this *ReportController) EditLayoutImg() {
 		br.ErrMsg = "参数解析失败,Err:" + err.Error()
 		return
 	}
-	//if req.Content == "" {
-	//	br.Msg = "报告内容不能为空"
-	//	return
-	//}
-	//更新标记key
+	//	if req.Content == "" {
+	//		br.Msg = "报告内容不能为空"
+	//		return
+	//	}
+	//
+	// 更新标记key
 	markStatus, err := services.UpdateReportEditMark(int(req.ReportId), 0, sysUser.AdminId, 1, sysUser.RealName, this.Lang)
 	if err != nil {
 		br.Msg = err.Error()
@@ -1189,7 +1242,7 @@ func (this *ReportController) EditLayoutImg() {
 	}
 	if markStatus.Status == 1 {
 		br.Msg = markStatus.Msg
-		//br.Ret = 202 //202 服务器已接受请求,但尚未处理。
+		// br.Ret = 202 //202 服务器已接受请求,但尚未处理。
 		return
 	}
 
@@ -1816,10 +1869,10 @@ func (this *ReportCommonController) ShareTransform() {
 // @author: Roc
 // @datetime 2024-06-21 09:19:05
 func init() {
-	//fixApproveRecord()
-	//fixChapterPermission()
-	//fixReportEs()
-	//fixSmartReport()
+	// fixApproveRecord()
+	// fixChapterPermission()
+	// fixReportEs()
+	// fixSmartReport()
 }
 
 // 修复研报审批数据
@@ -1835,7 +1888,7 @@ func fixApproveRecord() {
 		return
 	}
 	for _, recordItem := range list {
-		//fmt.Println(recordItem)
+		// fmt.Println(recordItem)
 		recordItem.NodeState = recordItem.State
 		recordItem.NodeApproveUserId = recordItem.ApproveUserId
 		recordItem.NodeApproveUserName = recordItem.ApproveUserName
@@ -1885,7 +1938,7 @@ func fixChapterPermission() {
 		}
 	}
 
-	//notIdList := []int{9675, 9675, 9740, 9749, 9768, 9773, 9791, 9792, 9793, 9850, 9851, 9852, 9852, 9852, 9853, 9854, 9856, 9857, 9857, 9858, 9859, 9860, 9861, 9862, 9862, 9863, 9866}
+	// notIdList := []int{9675, 9675, 9740, 9749, 9768, 9773, 9791, 9792, 9793, 9850, 9851, 9852, 9852, 9852, 9853, 9854, 9856, 9857, 9857, 9858, 9859, 9860, 9861, 9862, 9862, 9863, 9866}
 	notIdList := []int{}
 	allReportChapterList, err := models.GetAllReportChapter()
 	if err != nil {
@@ -2008,7 +2061,7 @@ func fixSmartReport() {
 	for _, v := range list {
 		fmt.Println(v)
 		addList = append(addList, &models.Report{
-			//Id:                  0,
+			// Id:                  0,
 			AddType:            1,
 			ClassifyIdFirst:    v.ClassifyIdFirst,
 			ClassifyNameFirst:  v.ClassifyNameFirst,
@@ -2024,7 +2077,7 @@ func fixSmartReport() {
 			PublishTime:        v.PublishTime,
 			Stage:              v.Stage,
 			MsgIsSend:          v.MsgIsSend,
-			//ThsMsgIsSend:        v.Tha,
+			// ThsMsgIsSend:        v.Tha,
 			Content:             v.Content,
 			VideoUrl:            v.VideoUrl,
 			VideoName:           v.VideoName,
@@ -2120,7 +2173,7 @@ func fixSmartReport() {
 func initPdf() {
 	inFile := "anNNgk3Bbi4LRULwcJgNOPrREYh5.pdf"
 	f2, err := services.GeneralWaterMarkPdf(inFile, "颜鹏 - 18170239278")
-	//f2, err := services.GeneralWaterMarkPdf(inFile, "上周美国馏分油库存累库95万桶,馏分油表需环比下降(-25.6万桶/日)。本期馏分油产量继续抬升,在供增需减的环比变动下库存持续累库。馏分油供应的增加我们认为可能和进口的油种有关,今年以来美国进口的中重质原油占比不断走高,尤其是5")
+	// f2, err := services.GeneralWaterMarkPdf(inFile, "上周美国馏分油库存累库95万桶,馏分油表需环比下降(-25.6万桶/日)。本期馏分油产量继续抬升,在供增需减的环比变动下库存持续累库。馏分油供应的增加我们认为可能和进口的油种有关,今年以来美国进口的中重质原油占比不断走高,尤其是5")
 	if err != nil {
 		fmt.Println("生成失败,ERR:", err)
 		return

+ 104 - 24
models/report.go

@@ -4,10 +4,12 @@ import (
 	sql2 "database/sql"
 	"errors"
 	"eta/eta_api/global"
+	"eta/eta_api/models/report"
 	"eta/eta_api/utils"
 	"fmt"
 	"github.com/rdlucklib/rdluck_tools/paging"
 	"gorm.io/gorm"
+	"gorm.io/gorm/clause"
 	"strings"
 	"time"
 )
@@ -90,6 +92,7 @@ type Report struct {
 	ReportCreateTime    time.Time `description:"报告时间创建时间"`
 	InheritReportId     int       `description:"待继承的报告ID"`
 	VoiceGenerateType   int       `description:"音频生成方式,0:系统生成,1:人工上传"`
+	FreeLayoutConfig    string    `description:"'自由布局配置"`
 }
 
 func (m *Report) AfterFind(db *gorm.DB) (err error) {
@@ -612,7 +615,7 @@ type AddReq struct {
 	HeadResourceId     int    `description:"版头资源ID"`
 	EndResourceId      int    `description:"版尾资源ID"`
 	CollaborateType    int8   `description:"协作方式,1:个人,2:多人协作。默认:1"`
-	ReportLayout       int8   `description:"报告布局,1:常规布局,2:智能布局。默认:1"`
+	ReportLayout       int8   `description:"报告布局,1:常规布局,2:智能布局,3:自由布局。默认:1"`
 	IsPublicPublish    int8   `description:"是否公开发布,1:是,2:否"`
 	InheritReportId    int    `description:"待继承的报告ID"`
 	GrantAdminIdList   []int  `description:"授权用户id列表"`
@@ -641,29 +644,30 @@ func AddReport(item *Report) (lastId int64, err error) {
 }
 
 type EditReq struct {
-	ReportId           int64  `description:"报告id"`
-	ClassifyIdFirst    int    `description:"一级分类id"`
-	ClassifyNameFirst  string `description:"一级分类名称"`
-	ClassifyIdSecond   int    `description:"二级分类id"`
-	ClassifyNameSecond string `description:"二级分类名称"`
-	ClassifyIdThird    int    `description:"三级分类id"`
-	ClassifyNameThird  string `description:"三级分类名称"`
-	Title              string `description:"标题"`
-	Abstract           string `description:"摘要"`
-	Author             string `description:"作者"`
-	Frequency          string `description:"频度"`
-	State              int    `description:"状态:1:未发布,2:已发布"`
-	Content            string `description:"内容"`
-	CreateTime         string `description:"创建时间"`
-	ContentStruct      string `description:"内容组件"`
-	HeadImg            string `description:"报告头图地址"`
-	EndImg             string `description:"报告尾图地址"`
-	CanvasColor        string `description:"画布颜色"`
-	NeedSplice         int    `description:"是否拼接版头版位的标记,主要是为了兼容历史报告。0-不需要 1-需要"`
-	HeadResourceId     int    `description:"版头资源ID"`
-	EndResourceId      int    `description:"版尾资源ID"`
+	ReportId               int64                `description:"报告id"`
+	ClassifyIdFirst        int                  `description:"一级分类id"`
+	ClassifyNameFirst      string               `description:"一级分类名称"`
+	ClassifyIdSecond       int                  `description:"二级分类id"`
+	ClassifyNameSecond     string               `description:"二级分类名称"`
+	ClassifyIdThird        int                  `description:"三级分类id"`
+	ClassifyNameThird      string               `description:"三级分类名称"`
+	Title                  string               `description:"标题"`
+	Abstract               string               `description:"摘要"`
+	Author                 string               `description:"作者"`
+	Frequency              string               `description:"频度"`
+	State                  int                  `description:"状态:1:未发布,2:已发布"`
+	Content                string               `description:"内容"`
+	FreeLayoutContentPages []report.ContentPage `description:"自由布局页面列表"`
+	CreateTime             string               `description:"创建时间"`
+	ContentStruct          string               `description:"内容组件"`
+	HeadImg                string               `description:"报告头图地址"`
+	EndImg                 string               `description:"报告尾图地址"`
+	CanvasColor            string               `description:"画布颜色"`
+	NeedSplice             int                  `description:"是否拼接版头版位的标记,主要是为了兼容历史报告。0-不需要 1-需要"`
+	HeadResourceId         int                  `description:"版头资源ID"`
+	EndResourceId          int                  `description:"版尾资源ID"`
 	//CollaborateType    int8   `description:"协作方式,1:个人,2:多人协作。默认:1"`
-	//ReportLayout       int8   `description:"报告布局,1:常规布局,2:智能布局。默认:1"`
+	//ReportLayout       int8   `description:"报告布局,1:常规布局,2:智能布局,3:自由布局。默认:1"`
 	IsPublicPublish  int8  `description:"是否公开发布,1:是,2:否"`
 	GrantAdminIdList []int `description:"授权用户id列表"`
 }
@@ -812,7 +816,6 @@ type SaveReportContent struct {
 	Content  string `description:"内容"`
 	ReportId int    `description:"报告id"`
 	NoChange int    `description:"内容是否未改变:1:内容未改变"`
-
 	// 以下是智能研报相关
 	ContentStruct  string `description:"内容组件"`
 	HeadImg        string `description:"报告头图地址"`
@@ -821,6 +824,9 @@ type SaveReportContent struct {
 	NeedSplice     int    `description:"是否拼接版头版位的标记,主要是为了兼容历史报告。0-不需要 1-需要"`
 	HeadResourceId int    `description:"版头资源ID"`
 	EndResourceId  int    `description:"版尾资源ID"`
+	//自由布局相关
+	FreeLayoutContentPages []report.ContentPage `description:"自由布局页面数据"`
+	FreeLayoutConfig       string               `description:"自由布局配置"`
 }
 
 //func EditReportContent(reportId int, content, contentSub string) (err error) {
@@ -1689,3 +1695,77 @@ type ReportShartUrlReq struct {
 type ReportShartUrlResp struct {
 	UrlToken string `description:"分享链接token"`
 }
+
+func InsertOrUpdateReportFreeLayoutContentPage(report *Report, ormList []*report.ReportFreeLayout) (err error) {
+	tx := global.DbMap[utils.DbNameReport].Begin()
+
+	defer func() {
+		if err != nil {
+			_ = tx.Rollback()
+			return
+		}
+		_ = tx.Commit()
+	}()
+	reportUpdateCols := []string{"Content", "ContentSub", "ContentStruct", "HeadImg", "EndImg", "CanvasColor", "HeadResourceId", "EndResourceId", "ModifyTime", "ContentModifyTime"}
+	err = tx.Model(&report).Select(reportUpdateCols).Updates(report).Error
+
+	tx.Clauses(clause.OnConflict{
+		Columns:   []clause.Column{{Name: "report_id"}, {Name: "report_chapter_id"}, {Name: "page"}},
+		DoUpdates: clause.AssignmentColumns([]string{"content", "content_struct", "modify_time", "is_deleted"}),
+	})
+	err = tx.Where("report_id = ?", report.Id).Update("is_deleted", 1).Error
+	if err != nil {
+		return
+	}
+	err = tx.CreateInBatches(ormList, len(ormList)).Error
+	if err != nil {
+		return
+	}
+
+	return
+}
+func UpdateChapterFreeLayoutContentPage(reportInfo *Report, chapterInfo *ReportChapter, updateCols []string, tickerList []*ReportChapterTicker, ormList []*report.ReportFreeLayout) (err error) {
+	tx := global.DbMap[utils.DbNameReport].Begin()
+	defer func() {
+		if err != nil {
+			_ = tx.Rollback()
+			return
+		}
+		_ = tx.Commit()
+	}()
+
+	if err = tx.Model(&reportInfo).Select([]string{"LastModifyAdminId", "LastModifyAdminName", "ModifyTime"}).Updates(reportInfo).Error; err != nil {
+		return
+	}
+	// 更新章节
+	if err = tx.Model(&chapterInfo).Select(updateCols).Updates(chapterInfo).Error; err != nil {
+		return
+	}
+	sql := ` DELETE FROM report_chapter_ticker WHERE report_chapter_id = ? `
+	// 清空并新增章节ticker
+	if err = tx.Exec(sql, chapterInfo.ReportChapterId).Error; err != nil {
+		return
+	}
+	tickerLen := len(tickerList)
+	if tickerLen > 0 {
+		err = tx.CreateInBatches(tickerList, len(tickerList)).Error
+		if err != nil {
+			return
+		}
+	}
+	tx.Clauses(clause.OnConflict{
+		Columns:   []clause.Column{{Name: "report_id"}, {Name: "report_chapter_id"}, {Name: "page"}},
+		DoUpdates: clause.AssignmentColumns([]string{"content", "content_struct", "modify_time", "is_deleted"}),
+	})
+	err = tx.Where("report_id = ? and report_chapter_id=? and is_chapter=1", reportInfo.Id, chapterInfo.ReportChapterId).Update("is_deleted", 1).Error
+	if err != nil {
+		return
+	}
+	err = tx.CreateInBatches(ormList, len(ormList)).Error
+	if err != nil {
+		return
+	}
+	reportUpdateCols := []string{"Content", "ContentSub", "ContentStruct", "HeadImg", "EndImg", "CanvasColor", "HeadResourceId", "EndResourceId", "ModifyTime", "ContentModifyTime"}
+	err = tx.Model(&reportInfo).Select(reportUpdateCols).Updates(reportInfo).Error
+	return
+}

+ 71 - 0
models/report/report_free_layout.go

@@ -0,0 +1,71 @@
+package report
+
+import (
+	"time"
+)
+
+type ReportFreeLayout struct {
+	Id              int       `gorm:"primaryKey;autoIncrement;column:id"` // 主键
+	ReportId        int       `gorm:"column:report_id"`                   // 研报Id
+	ReportChapterId int       `gorm:"column:report_chapter_id"`           // 章节Id
+	Page            int       `gorm:"column:page"`                        // 页码
+	IsChapter       int       `gorm:"column:is_chapter"`                  // 是否多章节
+	Content         string    `gorm:"column:content;size:255"`            // 内容
+	ContentStruct   string    `gorm:"column:content_struct;size:255"`     // 内容
+	IsDeleted       int       `gorm:"column:is_deleted"`                  //是否删除
+	CreateTime      time.Time `gorm:"column:create_time"`                 // 创建时间
+	ModifyTime      time.Time `gorm:"column:modify_time"`                 // 修改时间
+}
+type PagePositionEnum string
+
+const (
+	Left   PagePositionEnum = "left"
+	Right  PagePositionEnum = "right"
+	Center PagePositionEnum = "center"
+)
+
+type ContentPage struct {
+	Page            int    `json:"Page"`
+	Content         string `json:"Content"`
+	ContentStruct   string `json:"ContentStruct"`
+	ReportId        int    `json:"ChapterId"`
+	ReportChapterId int    `json:"ReportChapterId"`
+}
+
+func (cp *ContentPage) ToView(isChapter bool, ReportId int, ReportChapterId int) *ReportFreeLayout {
+	if isChapter {
+		return &ReportFreeLayout{
+			ReportId:        ReportId,
+			ReportChapterId: ReportChapterId,
+			Page:            cp.Page,
+			IsChapter:       1,
+			Content:         cp.Content,
+			ContentStruct:   cp.ContentStruct,
+			CreateTime:      time.Now(),
+		}
+	} else {
+		return &ReportFreeLayout{
+			ReportId:        ReportId,
+			ReportChapterId: ReportChapterId,
+			Page:            cp.Page,
+			IsChapter:       0,
+			Content:         cp.Content,
+			ContentStruct:   cp.ContentStruct,
+			CreateTime:      time.Now(),
+		}
+	}
+}
+
+func ToOrmViewList(srcList []ContentPage, isChapter bool, ReportId int, ReportChapterId int) (list []*ReportFreeLayout) {
+	for _, v := range srcList {
+		list = append(list, v.ToView(isChapter, ReportId, ReportChapterId))
+	}
+	return
+}
+
+// TableName 设置表名
+func (ReportFreeLayout) TableName() string {
+	return "report_free_layout"
+}
+
+

+ 2 - 0
models/report_chapter.go

@@ -222,6 +222,8 @@ type EditReportChapterReq struct {
 	CanvasColor    string `description:"画布颜色"`
 	HeadResourceId int    `description:"版头资源ID"`
 	EndResourceId  int    `description:"版尾资源ID"`
+	//自由布局研报相关
+	FreeLayoutContentPages []report.ContentPage `description:"自由布局内容"`
 }
 
 type EditTickList struct {