Browse Source

Merge branch 'eta/3.0' into debug

Roc 1 month ago
parent
commit
4724d14db4

+ 119 - 10
controllers/data_manage/excel/excel_info.go

@@ -1085,6 +1085,16 @@ func (c *ExcelInfoController) Edit() {
 		err = excel3.AddExcelDraft(excelDraftInfo)
 	}
 
+	// 判断是否清除该表引用
+	if req.IsColChange {
+		err = excel3.DeleteReferencedExcelConfig(excelInfo.UniqueCode)
+		if err != nil {
+			br.Msg = "操作失败"
+			br.ErrMsg = err.Error()
+			return
+		}
+	}
+
 	resp := response.AddExcelInfoResp{
 		ExcelInfoId: excelInfo.ExcelInfoId,
 		UniqueCode:  excelInfo.UniqueCode,
@@ -1550,6 +1560,8 @@ func (c *ExcelInfoController) GetExcelTableData() {
 	}
 	uniqueCode := c.GetString("UniqueCode")
 	fromScene, _ := c.GetInt("FromScene", 0)
+	referencedId, _ := c.GetInt("ReferencedId", 0)
+	uuid := c.GetString("Uuid")
 
 	var err error
 	if uniqueCode == `` {
@@ -1681,17 +1693,26 @@ func (c *ExcelInfoController) GetExcelTableData() {
 		}
 	}
 
+	// 获取表格引用
+	reference, err := excel3.GetReferencedExcelConfig(referencedId, fromScene, uniqueCode, uuid)
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取表格引用失败,Err:" + err.Error()
+		return
+	}
+
 	resp := response.ExcelTableDetailResp{
-		UniqueCode:    excelInfo.UniqueCode,
-		ExcelImage:    excelInfo.ExcelImage,
-		ExcelName:     excelInfo.ExcelName,
-		TableInfo:     tableData,
-		Config:        config,
-		SourcesFrom:   excelInfo.SourcesFrom,
-		ExcelSource:   excelSource,
-		ExcelSourceEn: excelSourceEn,
-		ExcelInfoId:   excelInfo.ExcelInfoId,
-		Source:        excelInfo.Source,
+		UniqueCode:            excelInfo.UniqueCode,
+		ExcelImage:            excelInfo.ExcelImage,
+		ExcelName:             excelInfo.ExcelName,
+		TableInfo:             tableData,
+		Config:                config,
+		SourcesFrom:           excelInfo.SourcesFrom,
+		ExcelSource:           excelSource,
+		ExcelSourceEn:         excelSourceEn,
+		ExcelInfoId:           excelInfo.ExcelInfoId,
+		Source:                excelInfo.Source,
+		ReferencedExcelConfig: reference,
 	}
 	br.Ret = 200
 	br.Success = true
@@ -3216,3 +3237,91 @@ func (c *ExcelInfoController) GetExcelRuleDetail() {
 	br.Ret = 200
 	br.Success = true
 }
+
+// GetExcelReferenceDetail
+// @Title 表格引用配置保存
+// @Description 表格引用配置保存
+// @Param   ExcelInfoRuleMappingId   query   int  true       "id"
+// @Success Ret=200 获取成功
+// @router /excel_info/reference/save [post]
+func (c *ExcelInfoController) SaveExcelReference() {
+	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"
+		br.Ret = 408
+		return
+	}
+	var req excel3.ExcelReferencesReq
+	err := json.Unmarshal(c.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	addList := make([]*excel3.ReferencedExcelConfig, 0)
+
+	exist, e := excel3.GetReferencedExcelConfig(req.ReferencedId, req.FromScene, req.UniqueCode, req.Uuid)
+	if e != nil && e.Error() != utils.ErrNoRow() {
+		br.Msg = "查找引用失败"
+		br.ErrMsg = "查找引用失败,Err:" + e.Error()
+		return
+	}
+	if exist.ReferencedExcelConfigId == 0 {
+		item := excel3.ReferencedExcelConfig{
+			UniqueCode:   req.UniqueCode,
+			ReferencedId: req.ReferencedId,
+			FromScene:    req.FromScene,
+			Uuid:         req.Uuid,
+			WidthList:    req.WidthList,
+			HeightList:   req.HeightList,
+			OpUserId:     sysUser.AdminId,
+			OpUserName:   sysUser.RealName,
+			CreateTime:   time.Now(),
+			ModifyTime:   time.Now(),
+		}
+		addList = append(addList, &item)
+	} else {
+		exist.WidthList = req.WidthList
+		exist.HeightList = req.HeightList
+		exist.OpUserId = sysUser.AdminId
+		exist.OpUserName = sysUser.RealName
+		exist.ModifyTime = time.Now()
+		err = excel3.UpdateReferencedExcelConfig(&exist)
+		if err != nil {
+			br.Msg = "更新引用失败"
+			br.ErrMsg = "更新引用失败,Err:" + err.Error()
+			return
+		}
+	}
+
+	if len(addList) > 0 {
+		err = excel3.AddReferencedExcelConfig(addList)
+		if err != nil && err.Error() != utils.ErrNoRow() {
+			br.Msg = "添加引用失败"
+			br.ErrMsg = "添加引用失败,Err:" + err.Error()
+			return
+		}
+	}
+
+	excelInfo, err := excel3.GetExcelInfoByUnicode(req.UniqueCode)
+	if err != nil {
+		br.Msg = "获取表格信息失败"
+		br.ErrMsg = "获取表格信息失败,Err:" + err.Error()
+		return
+	}
+	if excelInfo.ExcelInfoId > 0 {
+		//删除公共图库那边的缓存
+		_ = utils.Rc.Delete(utils.HZ_CHART_LIB_EXCEL_TABLE_DETAIL + ":" + excelInfo.UniqueCode)
+	}
+
+	br.Msg = "添加成功"
+	br.Ret = 200
+	br.Success = true
+}

+ 31 - 0
controllers/ppt_v2.go

@@ -4,6 +4,7 @@ import (
 	"encoding/json"
 	"eta_gn/eta_api/models"
 	"eta_gn/eta_api/models/company"
+	"eta_gn/eta_api/models/data_manage/excel"
 	"eta_gn/eta_api/models/system"
 	"eta_gn/eta_api/services"
 	"eta_gn/eta_api/services/ppt"
@@ -180,6 +181,36 @@ func (this *PptV2Controller) AddPpt() {
 			return
 		}
 		msg = "新增成功"
+
+		excelReferences := make([]*excel.ReferencedExcelConfig, 0)
+		for _, r := range req.ExcelReferences {
+			refItem := excel.ReferencedExcelConfig{
+				UniqueCode:   r.UniqueCode,
+				ReferencedId: int(newId),
+				FromScene:    utils.TableReferencedByPPT,
+				Uuid:         r.Uuid,
+				WidthList:    r.WidthList,
+				HeightList:   r.HeightList,
+				OpUserId:     this.SysUser.AdminId,
+				OpUserName:   this.SysUser.RealName,
+				CreateTime:   time.Now(),
+				ModifyTime:   time.Now(),
+			}
+			excelReferences = append(excelReferences, &refItem)
+		}
+		if len(excelReferences) > 0 {
+			err = excel.AddReferencedExcelConfig(excelReferences)
+			if err != nil {
+				br.Msg = "新增引用失败"
+				br.ErrMsg = "新增引用失败,Err:" + err.Error()
+				return
+			}
+		}
+
+		// 合并ppt后,将ppt的表格关系做处理
+		if len(req.MergePptIdList) > 0 {
+			services.HandlerMergePptTableReferenced(req.MergePptIdList, int(newId), this.SysUser.AdminId, this.SysUser.RealName, utils.TableReferencedByPPT)
+		}
 	} else {
 		newId = req.PptId
 

+ 7 - 0
controllers/report_chapter.go

@@ -382,6 +382,8 @@ func (this *ReportController) EditDayWeekChapter() {
 	// 更新章节及指标
 	contentSub := ""
 	if req.Content != "" {
+		// 处理关联excel的表格id
+		req.Content = services.HandleReportContentTable(reportInfo.Id, req.Content)
 		e := utils.ContentXssCheck(req.Content)
 		if e != nil {
 			br.Msg = "存在非法标签"
@@ -431,6 +433,9 @@ func (this *ReportController) EditDayWeekChapter() {
 	reportChapterInfo.LastModifyAdminId = sysUser.AdminId
 	reportChapterInfo.LastModifyAdminName = sysUser.RealName
 	reportChapterInfo.ContentModifyTime = time.Now()
+	if req.ContentStruct != `` {
+		req.ContentStruct = services.HandleReportContentStructTable(reportChapterInfo.ReportId, req.ContentStruct)
+	}
 	reportChapterInfo.ContentStruct = html.EscapeString(req.ContentStruct)
 
 	updateCols = append(updateCols, "Author", "Content", "ContentSub", "IsEdit", "ModifyTime")
@@ -849,6 +854,8 @@ func (this *ReportController) GetDayWeekChapter() {
 	chapterItem.Content = html.UnescapeString(chapterItem.Content)
 	chapterItem.ContentSub = html.UnescapeString(chapterItem.ContentSub)
 	chapterItem.ContentStruct = html.UnescapeString(chapterItem.ContentStruct)
+	chapterItem.Content = services.HandleReportContentTable(chapterItem.ReportId, chapterItem.Content)
+	chapterItem.ContentStruct = services.HandleReportContentStructTable(chapterItem.ReportId, chapterItem.ContentStruct)
 
 	// 授权用户列表map
 	chapterGrantIdList := make([]int, 0)

+ 10 - 0
controllers/report_v2.go

@@ -596,6 +596,9 @@ func (this *ReportController) Edit() {
 		return
 	}
 
+	req.Content = services.HandleReportContentTable(int(req.ReportId), req.Content)
+	req.ContentStruct = services.HandleReportContentStructTable(int(req.ReportId), req.ContentStruct)
+
 	// 编辑报告信息
 	err, errMsg := services.EditReport(reportInfo, req, sysUser)
 	if err != nil {
@@ -707,6 +710,13 @@ func (this *ReportController) Detail() {
 		item.EndStyle = endResource.Style
 	}
 
+	item.Content = services.HandleReportContentTable(item.Id, item.Content)
+	item.ContentStruct = services.HandleReportContentStructTable(item.Id, item.ContentStruct)
+	for _, v := range chapterList {
+		v.Content = services.HandleReportContentTable(item.Id, v.Content)
+		v.ContentStruct = services.HandleReportContentStructTable(item.Id, v.ContentStruct)
+	}
+
 	resp := &models.ReportDetailView{
 		ReportDetail: item,
 		ChapterList:  chapterList,

+ 174 - 0
models/data_manage/excel/referenced_excel_config.go

@@ -0,0 +1,174 @@
+package excel
+
+import (
+	"eta_gn/eta_api/global"
+	"eta_gn/eta_api/utils"
+	"time"
+)
+
+type ReferencedExcelConfig struct {
+	ReferencedExcelConfigId int       `orm:"column(referenced_excel_config_id);pk;auto" ` // excel表格配置id
+	UniqueCode              string    // 表格唯一编码
+	ReferencedId            int       // 被引用的id,报告就是报告id,pptId
+	FromScene               int       // 引用类型 1智能研报 2研报列表 3英文研报 4PPT 5英文ppt
+	Uuid                    string    // 引用唯一标识
+	WidthList               string    // 宽度数组
+	HeightList              string    // 高度数组
+	OpUserId                int       // 当前编辑操作的用户id
+	OpUserName              string    // 当前编辑的用户名称(冗余字段,避免查表)
+	CreateTime              time.Time // 创建时间
+	Content                 string    // 内容
+	ModifyTime              time.Time // 修改时间
+}
+
+type ExcelReferencesReq struct {
+	UniqueCode   string `description:"表格唯一编码"`
+	ReferencedId int    `description:"被引用的ID"`
+	FromScene    int    `description:"引用类型 1智能研报 2研报列表 3英文研报 4PPT 5英文PPT"`
+	Uuid         string `description:"引用唯一标识"`
+	WidthList    string `description:"宽度数组"`
+	HeightList   string `description:"高度数组"`
+}
+
+// add
+func AddReferencedExcelConfig(items []*ReferencedExcelConfig) (err error) {
+	err = global.DmSQL["data"].CreateInBatches(items, utils.MultiAddNum).Error
+
+	return
+}
+
+// getByCode
+func GetReferencedExcelConfigByUniqueCode(uniqueCode string) (item ReferencedExcelConfig, err error) {
+	sql := ` SELECT * FROM referenced_excel_config WHERE referenced_excel_unique_code = ? `
+	err = global.DmSQL["data"].Raw(sql, uniqueCode).First(&item).Error
+
+	return
+}
+
+// getByCode
+func GetReferencedExcelConfig(referencedId, fromScene int, uniqueCode, uuid string) (item ReferencedExcelConfig, err error) {
+	sql := ` SELECT * FROM referenced_excel_config WHERE referenced_id = ? AND from_scene = ? AND unique_code = ? AND  uuid= ? `
+	err = global.DmSQL["data"].Raw(sql, referencedId, fromScene, uniqueCode, uuid).First(&item).Error
+
+	return
+}
+
+// update
+func UpdateReferencedExcelConfig(item *ReferencedExcelConfig) (err error) {
+	err = global.DmSQL["data"].Select([]string{"width_list", "height_list", "op_user_id", "op_user_name", "modify_time"}).Updates(item).Error
+
+	return
+}
+
+// delete
+func DeleteReferencedExcelConfig(uniqueCode string) (err error) {
+	sql := `DELETE FROM referenced_excel_config WHERE unique_code=? `
+	err = global.DmSQL["data"].Exec(sql, uniqueCode).Error
+
+	return
+}
+
+// GetReferencedExcelConfigList
+// @Description: 根据来源类型和来源id获取所有配置列表
+// @author: Roc
+// @datetime 2025-01-09 14:31:20
+// @param referencedId int
+// @param fromScene int
+// @return items []ReferencedExcelConfig
+// @return err error
+func GetReferencedExcelConfigList(referencedId, fromScene int) (items []ReferencedExcelConfig, err error) {
+	sql := ` SELECT * FROM referenced_excel_config WHERE referenced_id = ? AND from_scene = ? `
+	err = global.DmSQL["data"].Raw(sql, referencedId, fromScene).Find(&items).Error
+
+	return
+}
+
+// CopyReferencedExcelConfigByReferencedIdAndFromScene
+// @Description: 根据原引用Id和引用类型创建新的表格关系
+// @author: Roc
+// @datetime 2025-01-09 15:02:43
+// @param oldReferencedId int
+// @param oldFromScene int
+// @param newReferencedId int
+// @param newFromScene int
+// @param sysUserId int
+// @param sysUserName string
+// @return err error
+func CopyReferencedExcelConfigByReferencedIdAndFromScene(oldReferencedId, oldFromScene, newReferencedId, newFromScene, sysUserId int, sysUserName string) (addList []*ReferencedExcelConfig, err error) {
+	var items []ReferencedExcelConfig
+	sql := ` SELECT * FROM referenced_excel_config WHERE referenced_id = ? AND from_scene = ? `
+	err = global.DmSQL["data"].Raw(sql, oldReferencedId, oldFromScene).Find(&items).Error
+	if err != nil {
+		return
+	}
+
+	addList = make([]*ReferencedExcelConfig, 0)
+	for _, v := range items {
+		addList = append(addList, &ReferencedExcelConfig{
+			ReferencedExcelConfigId: 0,
+			UniqueCode:              v.UniqueCode,
+			ReferencedId:            newReferencedId,
+			FromScene:               newFromScene,
+			Uuid:                    v.Uuid,
+			WidthList:               v.WidthList,
+			HeightList:              v.HeightList,
+			OpUserId:                sysUserId,
+			OpUserName:              sysUserName,
+			CreateTime:              time.Now(),
+			Content:                 v.Content,
+			ModifyTime:              time.Now(),
+		})
+	}
+	// 批量复制表格关系
+	err = global.DmSQL["data"].CreateInBatches(addList, utils.MultiAddNum).Error
+
+	return
+}
+
+// CopyReferencedExcelConfigByReferencedIdListAndFromScene
+// @Description: 根据原引用Id列表和引用类型创建新的表格关系
+// @author: Roc
+// @datetime 2025-01-09 17:37:47
+// @param oldReferencedIdList []int
+// @param oldFromScene int
+// @param newReferencedId int
+// @param newFromScene int
+// @param sysUserId int
+// @param sysUserName string
+// @return addList []*ReferencedExcelConfig
+// @return err error
+func CopyReferencedExcelConfigByReferencedIdListAndFromScene(oldReferencedIdList []int, oldFromScene, newReferencedId, newFromScene, sysUserId int, sysUserName string) (addList []*ReferencedExcelConfig, err error) {
+	num := len(oldReferencedIdList)
+	if num <= 0 {
+		return
+	}
+
+	var items []ReferencedExcelConfig
+	sql := ` SELECT * FROM referenced_excel_config WHERE referenced_id in (` + utils.GetOrmInReplace(num) + `) AND from_scene = ? group by unique_code,uuid `
+	err = global.DmSQL["data"].Raw(sql, oldReferencedIdList, oldFromScene).Find(&items).Error
+	if err != nil {
+		return
+	}
+
+	addList = make([]*ReferencedExcelConfig, 0)
+	for _, v := range items {
+		addList = append(addList, &ReferencedExcelConfig{
+			ReferencedExcelConfigId: 0,
+			UniqueCode:              v.UniqueCode,
+			ReferencedId:            newReferencedId,
+			FromScene:               newFromScene,
+			Uuid:                    v.Uuid,
+			WidthList:               v.WidthList,
+			HeightList:              v.HeightList,
+			OpUserId:                sysUserId,
+			OpUserName:              sysUserName,
+			CreateTime:              time.Now(),
+			Content:                 v.Content,
+			ModifyTime:              time.Now(),
+		})
+	}
+	// 批量复制表格关系
+	err = global.DmSQL["data"].CreateInBatches(addList, utils.MultiAddNum).Error
+
+	return
+}

+ 1 - 0
models/data_manage/excel/request/excel_info.go

@@ -39,6 +39,7 @@ type EditExcelInfoReq struct {
 	Content         string      `description:"Excel表格内容"`
 	TableData       interface{} `description:"自定义表格的数据内容"`
 	SourcesFrom     string      `description:"图表来源"`
+	IsColChange     bool        `description:"是否修改过行列,true时清空引用"`
 }
 
 // SetExcelInfoImageReq 设置excel表格图片请求

+ 1 - 0
models/data_manage/excel/request/mixed_table.go

@@ -141,6 +141,7 @@ type MixCellShowStyle struct {
 	Color           string      `description:"颜色值,#RRG" json:"color"`
 	BackgroundColor string      `description:"背景颜色值,#RRG" json:"background-color"`
 	Align           string      `description:"对齐方式:left|center|right" json:"align"`
+	FontSize        string      `description:"字号大小" json:"font-size"`
 }
 
 type DateDataBeforeAfterReq struct {

+ 11 - 10
models/data_manage/excel/response/excel_info.go

@@ -23,16 +23,17 @@ type ExcelListResp struct {
 
 // ExcelTableDetailResp  excel表格详情
 type ExcelTableDetailResp struct {
-	UniqueCode    string `description:"表格唯一code"`
-	ExcelImage    string `description:"表格截图"`
-	ExcelName     string `description:"表格名称"`
-	TableInfo     excel.TableData
-	Config        ExcelTableDetailConfigResp
-	SourcesFrom   string `description:"图表来源"`
-	ExcelSource   string `description:"表格来源str"`
-	ExcelSourceEn string `description:"表格来源(英文)"`
-	ExcelInfoId   int    `description:"表id"`
-	Source        int    `description:"表格来源"`
+	UniqueCode            string `description:"表格唯一code"`
+	ExcelImage            string `description:"表格截图"`
+	ExcelName             string `description:"表格名称"`
+	TableInfo             excel.TableData
+	Config                ExcelTableDetailConfigResp
+	SourcesFrom           string                       `description:"图表来源"`
+	ExcelSource           string                       `description:"表格来源str"`
+	ExcelSourceEn         string                       `description:"表格来源(英文)"`
+	ExcelInfoId           int                          `description:"表id"`
+	Source                int                          `description:"表格来源"`
+	ReferencedExcelConfig excel2.ReferencedExcelConfig `description:"表格引用信息"`
 }
 
 // ExcelTableDetailConfigResp

+ 2 - 1
models/data_manage/predict_edb_conf.go

@@ -138,7 +138,8 @@ func GetPredictEdbInfoAllCalculate(edbInfoIdList []int) (list []*EdbInfo, err er
 	if num <= 0 {
 		return
 	}
-	sql := ` SELECT DISTINCT b.* FROM predict_edb_conf AS a
+	sql := ` SELECT DISTINCT b.edb_info_id,b.edb_info_type,b.source_name,b.source,b.edb_code,b.edb_name,b.edb_name_source,b.frequency,b.unit,b.start_date,b.end_date,b.classify_id,b.sys_user_id,b.sys_user_real_name,b.create_time,b.modify_time,b.unique_code,b.min_value,b.max_value,b.edb_type,b.is_update,b.sort,b.latest_date,b.latest_value,b.move_type,b.move_frequency,b.no_update,b.server_url,b.edb_name_en,b.unit_en,b.chart_image,b.calendar,b.empty_type,b.max_empty_type,b.data_date_type,b.manual_save,b.terminal_code,b.data_update_time,b.er_data_update_date,b.source_index_name,b.end_value,b.sub_source,b.sub_source_name,b.indicator_code,b.stock_code,b.is_join_permission,b.base_modify_time,b.is_static_data,b.set_update_time,b.original_edb_code,b.public_status,b.edb_public_classify_id,b.public_time,b.public_sort
+ FROM predict_edb_conf AS a
 			 INNER JOIN edb_info AS b ON a.source_edb_info_id=b.edb_info_id
 	        WHERE a.predict_edb_info_id in (` + utils.GetOrmInReplace(num) + `)
 			 ORDER BY b.edb_info_id ASC `

+ 9 - 6
models/ppt_v2.go

@@ -2,6 +2,7 @@ package models
 
 import (
 	"eta_gn/eta_api/global"
+	"eta_gn/eta_api/models/data_manage/excel"
 	"eta_gn/eta_api/utils"
 	"fmt"
 	"strings"
@@ -150,12 +151,14 @@ type AddPptV2Req struct {
 		BackIndex              int    `description:"背景图片下标"`
 		TemplateType           int    `description:"模版id"`
 	} `description:"首页"`
-	Abstract         string `description:"摘要"`
-	CollaborateUsers string `description:"协作人IDs, 英文逗号分隔"`
-	Content          string `description:"ppt的json数据"`
-	GroupId          int64  `description:"目录id"`
-	CoverContent     string `description:"封面图内容-JSON数据"`
-	TitleSetting     string `description:"PPT标题设置"`
+	Abstract         string                     `description:"摘要"`
+	CollaborateUsers string                     `description:"协作人IDs, 英文逗号分隔"`
+	Content          string                     `description:"ppt的json数据"`
+	GroupId          int64                      `description:"目录id"`
+	CoverContent     string                     `description:"封面图内容-JSON数据"`
+	TitleSetting     string                     `description:"PPT标题设置"`
+	ExcelReferences  []excel.ExcelReferencesReq `description:"引用的Excel信息"`
+	MergePptIdList   []int                      `description:"合并的ppt的Id列表"`
 }
 
 type AddPptResp struct {

+ 1 - 1
services/data/chart_classify.go

@@ -292,7 +292,7 @@ func AddChartClassify(chartClassifyName string, parentId, level, source int, lan
 	}
 
 	// 更改分类id完整路径path
-	updateCols := []string{"ClassifyIdPath"}
+	updateCols := []string{"ChartClassifyIdPath"}
 	classifyInfo.ChartClassifyIdPath = fmt.Sprint(classifyIdPath, classifyInfo.ChartClassifyId)
 	if parentId == 0 { //一级目录的rootId等于自己本身
 		classifyInfo.RootId = classifyInfo.ChartClassifyId

+ 3 - 0
services/excel/lucky_sheet.go

@@ -1778,6 +1778,9 @@ func GetTableDataByMixedTableData(config [][]request.MixedTableCellDataReq, hide
 						tmp.HorizontalType = 2
 						tmp.Ht = 2
 					}
+					if styleConfig.FontSize != "" {
+						tmp.Fs = styleConfig.FontSize
+					}
 					tmp.Monitor = showFormatValue
 					// 如果没有showValue, 则使用value
 					if cell.ShowValue == "" {

+ 90 - 6
services/ppt.go

@@ -4,11 +4,13 @@ import (
 	"encoding/json"
 	"errors"
 	"eta_gn/eta_api/models"
+	"eta_gn/eta_api/models/data_manage/excel"
 	"eta_gn/eta_api/models/system"
 	"eta_gn/eta_api/services/alarm_msg"
 	"eta_gn/eta_api/services/ppt2img"
 	"eta_gn/eta_api/utils"
 	"fmt"
+	"html"
 	"sort"
 	"time"
 )
@@ -37,6 +39,7 @@ type PPTContentElements struct {
 	SheetId     string `json:"sheetId"`
 	SheetHeight string `json:"sheetHeight"`
 	Src         string `json:"src"`
+	Uid         string `json:"uid"`
 }
 
 // SavePPTReport 保存PPT报告
@@ -159,14 +162,17 @@ func SavePPTReport(pptId, classifyId int, title string, adminInfo *system.Admin)
 		reportReq.IsPublicPublish = 1
 	}
 
-	newReportId, newCode, _, e := CreateNewReport(*reportReq, adminInfo)
+	newReportInfo, _, e := CreateNewReport(*reportReq, adminInfo)
 	if e != nil {
 		errMsg = "转换失败"
 		err = errors.New("新增报告失败, Err: " + e.Error())
 		return
 	}
-	reportId = int(newReportId)
-	reportCode = newCode
+	reportId = newReportInfo.Id
+	reportCode = newReportInfo.ReportCode
+
+	// ppt转报告后,将ppt的表格关系做处理
+	handlerPptToReportTableReferenced(pptId, reportId)
 
 	// 更新报告中的ppt图片
 	go saveReportPptImg(pptId, reportId, item.PptxUrl)
@@ -235,12 +241,12 @@ func pptContent2Html(content string, isEnglish bool) (htm string, err error) {
 				case ElementsTypeChart:
 					if isEnglish {
 						// 英文研报图表src多加一个fromPage=en, 表格暂时没有区分
-						htmlContent += fmt.Sprintf(`<iframe src="%s/chartshow?code=%s&fromPage=en" width="100%%" height="350" style="border-width:0px; min-height:350px;"></iframe>`, chartRoot, v.ChartId)
+						htmlContent += fmt.Sprintf(`<iframe src="%s/chartshow?code=%s&fromPage=en&uid=%s" width="100%%" height="350" style="border-width:0px; min-height:350px;"></iframe>`, chartRoot, v.ChartId, v.Uid)
 						break
 					}
-					htmlContent += fmt.Sprintf(`<iframe src="%s/chartshow?code=%s" width="100%%" height="350" style="border-width:0px; min-height:350px;"></iframe>`, chartRoot, v.ChartId)
+					htmlContent += fmt.Sprintf(`<iframe src="%s/chartshow?code=%s&uid=%s" width="100%%" height="350" style="border-width:0px; min-height:350px;" class="iframe%s"></iframe>`, chartRoot, v.ChartId, v.Uid, v.Uid)
 				case ElementsTypeSheet:
-					htmlContent += fmt.Sprintf(`<iframe src="%s/sheetshow?code=%s" class="iframe%s" width="100%%" height="%s" style="border-width:0px;"></iframe>`, chartRoot, v.SheetId, v.SheetId, v.SheetHeight)
+					htmlContent += fmt.Sprintf(`<iframe src="%s/sheetshow?code=%s&uid=%s" class="iframe%s" width="100%%" height="%s" style="border-width:0px;"></iframe>`, chartRoot, v.SheetId, v.Uid, v.Uid, v.SheetHeight)
 				}
 				htmlContent += htmlSuffix
 			}
@@ -384,3 +390,81 @@ func UpdatePptEditing(pptId, status, userId int, userName string, isEn bool) (re
 	}
 	return
 }
+
+// handlerPptToReportTableReferenced
+// @Description: ppt转报告后,需要同时继承原来ppt中表格的拖动数据逻辑
+// @author: Roc
+// @datetime 2025-01-09 16:51:11
+// @param pptId int
+// @param reportId int
+func handlerPptToReportTableReferenced(pptId, reportId int) {
+	var err error
+	defer func() {
+		if err != nil {
+			utils.FileLog.Error("ppt转报告后,报告与动态表格关联处理失败,PPT的ID:%d,新报告ID:%d,Err:%s", pptId, reportId, err.Error())
+		}
+	}()
+	reportInfo, err := models.GetReportByReportId(reportId)
+	if err != nil {
+		return
+	}
+
+	newFromScene := utils.TableReferencedByReport
+	addList, err := excel.CopyReferencedExcelConfigByReferencedIdAndFromScene(pptId, utils.TableReferencedByPPT, reportInfo.Id, newFromScene, reportInfo.AdminId, reportInfo.AdminRealName)
+	if err != nil {
+		return
+	}
+
+	if len(addList) > 0 {
+		// 修改内容
+		content := HandleReportContentTableAndScene(reportInfo.Id, newFromScene, html.UnescapeString(reportInfo.Content))
+		reportInfo.Content = html.EscapeString(content)
+		reportInfo.ContentStruct = HandleReportContentStructTableAndScene(reportInfo.Id, newFromScene, reportInfo.ContentStruct)
+		err = reportInfo.Update([]string{"Content", "ContentStruct"})
+		if err != nil {
+			return
+		}
+
+		if reportInfo.HasChapter == 1 {
+			chapterList, tmpErr := models.GetChapterListByReportId(reportInfo.Id)
+			if tmpErr != nil {
+				err = tmpErr
+				return
+			}
+			for _, v := range chapterList {
+				chapterContent := HandleReportContentTableAndScene(reportInfo.Id, newFromScene, html.UnescapeString(v.Content))
+				v.Content = html.EscapeString(chapterContent)
+				v.ContentStruct = HandleReportContentStructTableAndScene(reportInfo.Id, newFromScene, v.ContentStruct)
+				err = v.Update([]string{"Content", "ContentStruct"})
+				if err != nil {
+					return
+				}
+			}
+		}
+	}
+
+}
+
+// HandlerMergePptTableReferenced
+// @Description: 多ppt合并生成新的ppt,需要同时继承原来所有ppt中表格的拖动数据逻辑
+// @author: Roc
+// @datetime 2025-01-09 16:51:03
+// @param pptId int
+// @param enPptId int
+// @param sysUserId int
+// @param sysUserName string
+// @param fromScene int
+func HandlerMergePptTableReferenced(oldPptIdList []int, pptId, sysUserId int, sysUserName string, fromScene int) {
+	var err error
+	defer func() {
+		if err != nil {
+			utils.FileLog.Error("ppt转英文PPT后,英文PPT与动态表格关联处理失败,待合并的PPT的ID:%v,英文ppt的ID:%d,Err:%s", oldPptIdList, pptId, err.Error())
+		}
+	}()
+
+	_, err = excel.CopyReferencedExcelConfigByReferencedIdListAndFromScene(oldPptIdList, fromScene, pptId, fromScene, sysUserId, sysUserName)
+	if err != nil {
+		return
+	}
+
+}

+ 2 - 2
services/report.go

@@ -489,7 +489,7 @@ func PcCreateAndUploadSunCode(scene, page string) (imgUrl string, err error) {
 }
 
 // CreateNewReport 创建新报告
-func CreateNewReport(req models.AddReq, adminInfo *system.Admin) (newReportId int64, reportCode, errMsg string, err error) {
+func CreateNewReport(req models.AddReq, adminInfo *system.Admin) (item *models.Report, errMsg string, err error) {
 	contentSub := ""
 	if req.Content != "" {
 		e := utils.ContentXssCheck(req.Content)
@@ -519,7 +519,7 @@ func CreateNewReport(req models.AddReq, adminInfo *system.Admin) (newReportId in
 		return
 	}
 
-	item := new(models.Report)
+	item = new(models.Report)
 	item.AddType = req.AddType
 	item.ClassifyIdFirst = req.ClassifyIdFirst
 	item.ClassifyNameFirst = req.ClassifyNameFirst

+ 296 - 0
services/report_v2.go

@@ -2,14 +2,17 @@ package services
 
 import (
 	"archive/zip"
+	"encoding/json"
 	"errors"
 	"eta_gn/eta_api/models"
+	"eta_gn/eta_api/models/data_manage/excel"
 	"eta_gn/eta_api/models/report"
 	"eta_gn/eta_api/models/report_approve"
 	"eta_gn/eta_api/models/system"
 	"eta_gn/eta_api/utils"
 	"fmt"
 	"html"
+	"net/url"
 	"os"
 	"path"
 	"strconv"
@@ -18,6 +21,7 @@ import (
 
 	"github.com/rdlucklib/rdluck_tools/file"
 	"github.com/rdlucklib/rdluck_tools/http"
+	html2 "golang.org/x/net/html"
 )
 
 // AddReportAndChapter
@@ -103,6 +107,11 @@ func AddReportAndChapter(reportInfo *models.Report, inheritReportId int, grantAd
 		go models.ModifyReportCode(reportId, reportCode)
 	}
 
+	// 如果是继承报告,那么同时需要继承被引用的表格设置
+	if reportInfo.InheritReportId > 0 {
+		handlerReportTableReferenced(reportInfo)
+	}
+
 	// 报告权限处理
 	go func() {
 		handleReportPermission(reportId, minClassifyId)
@@ -1628,3 +1637,290 @@ func PublishReportV2(reportId int, sysUser *system.Admin) (tips string, err erro
 	}()
 	return
 }
+
+// handlerReportTableReferenced
+// @Description: 继承报告后,需要同时继承原来报告中表格的拖动数据逻辑
+// @author: Roc
+// @datetime 2025-01-09 15:35:55
+// @param reportInfo *models.Report
+func handlerReportTableReferenced(reportInfo *models.Report) {
+	var err error
+	defer func() {
+		if err != nil {
+			utils.FileLog.Error("报告表关联处理失败,旧报告ID:%d,新报告ID:%d,Err:%s", reportInfo.InheritReportId, reportInfo.Id, err.Error())
+		}
+	}()
+	addList, err := excel.CopyReferencedExcelConfigByReferencedIdAndFromScene(reportInfo.InheritReportId, utils.TableReferencedByReport, reportInfo.Id, utils.TableReferencedByReport, reportInfo.AdminId, reportInfo.AdminRealName)
+	if err != nil {
+		return
+	}
+
+	if len(addList) > 0 {
+		// 修改内容
+		reportInfo.Content = HandleReportContentTable(reportInfo.Id, reportInfo.Content)
+		reportInfo.ContentStruct = HandleReportContentStructTable(reportInfo.Id, reportInfo.ContentStruct)
+		err = reportInfo.Update([]string{"Content", "ContentStruct"})
+		if err != nil {
+			return
+		}
+
+		if reportInfo.HasChapter == 1 {
+			chapterList, tmpErr := models.GetChapterListByReportId(reportInfo.Id)
+			if tmpErr != nil {
+				err = tmpErr
+				return
+			}
+			for _, v := range chapterList {
+				v.Content = HandleReportContentTable(reportInfo.Id, v.Content)
+				v.ContentStruct = HandleReportContentStructTable(reportInfo.Id, v.ContentStruct)
+				err = v.Update([]string{"Content", "ContentStruct"})
+				if err != nil {
+					return
+				}
+			}
+		}
+	}
+
+}
+
+// HandleReportContentTable
+// @Description: 处理报告内容(动态表格添加报告来源id)(跟另一个需求代码冲突了,不好处理,只能额外写个方法出来使用了)
+// @author: Roc
+// @datetime 2025-01-09 13:25:41
+// @param reportId int
+// @param body string
+// @return newBody string
+func HandleReportContentTable(reportId int, body string) (newBody string) {
+	if body == `` {
+		return
+	}
+	newBody = body
+
+	// 解析HTML
+	doc, err := html2.Parse(strings.NewReader(body))
+	if err != nil {
+		fmt.Println("Error parsing HTML:", err)
+		return
+	}
+
+	replaceIframeSrcTable(doc, reportId, 0)
+
+	// 输出修改后的HTML
+	var modifiedHtml strings.Builder
+	err = html2.Render(&modifiedHtml, doc)
+	if err != nil {
+		fmt.Println("Error rendering HTML:", err)
+		return
+	}
+
+	newBody = modifiedHtml.String()
+	fmt.Println(newBody)
+
+	return
+}
+
+// HandleReportContentTableAndScene
+// @Description: 处理报告内容(动态表格添加报告来源id)(跟另一个需求代码冲突了,不好处理,只能额外写个方法出来使用了)
+// @author: Roc
+// @datetime 2025-01-10 10:15:39
+// @param reportId int
+// @param fromScene int
+// @param body string
+// @return newBody string
+func HandleReportContentTableAndScene(reportId, fromScene int, body string) (newBody string) {
+	if body == `` {
+		return
+	}
+	newBody = body
+
+	// 解析HTML
+	doc, err := html2.Parse(strings.NewReader(body))
+	if err != nil {
+		fmt.Println("Error parsing HTML:", err)
+		return
+	}
+
+	replaceIframeSrcTable(doc, reportId, fromScene)
+
+	// 输出修改后的HTML
+	var modifiedHtml strings.Builder
+	err = html2.Render(&modifiedHtml, doc)
+	if err != nil {
+		fmt.Println("Error rendering HTML:", err)
+		return
+	}
+
+	newBody = modifiedHtml.String()
+
+	return
+}
+
+// replaceIframeSrc 遍历HTML节点,替换iframe的src属性
+func replaceIframeSrcTable(n *html2.Node, reportId, fromScene int) {
+	if n.Type == html2.ElementNode && n.Data == "iframe" {
+		for i, attr := range n.Attr {
+			if attr.Key == "src" {
+				newLink := handleTableLinkReportId(attr.Val, reportId, fromScene)
+				// 替换原来的链接
+				n.Attr[i].Val = newLink
+				break
+			}
+		}
+	}
+	// 递归处理子节点
+	for c := n.FirstChild; c != nil; c = c.NextSibling {
+		replaceIframeSrcTable(c, reportId, fromScene)
+	}
+}
+
+// handleTableLinkReportId 链接添加token
+func handleTableLinkReportId(link string, reportId, fromScene int) string {
+	var err error
+	defer func() {
+		if err != nil {
+			utils.FileLog.Info("处理链接失败,ERR:" + err.Error())
+		}
+	}()
+	if link == `` {
+		return link
+	}
+	parsedURL, err := url.Parse(link)
+	if err != nil {
+		return link
+	}
+
+	// 获取查询参数
+	queryParams := parsedURL.Query()
+
+	// 先移除sourceId参数,避免莫名其妙的这个值入库了
+	queryParams.Del("sourceId")
+
+	queryParams.Add("sourceId", fmt.Sprint(reportId))
+
+	if fromScene > 0 {
+		queryParams.Del("fromScene")
+		queryParams.Add("fromScene", fmt.Sprint(fromScene))
+	}
+
+	// 更新URL的查询参数
+	parsedURL.RawQuery = queryParams.Encode()
+
+	// 在链接后面添加一个来源值
+	return parsedURL.String()
+}
+
+// HandleReportContentStructTable
+// @Description: 处理内容组件的表格链接(跟另一个需求代码冲突了,不好处理,只能额外写个方法出来使用了)
+// @author: Roc
+// @datetime 2025-01-09 13:40:35
+// @param reportId int
+// @param body string
+// @return newBody string
+func HandleReportContentStructTable(reportId int, body string) (newBody string) {
+	if body == `` {
+		return
+	}
+	newBody = body
+
+	// 解析JSON数据到map[string]interface{}
+	var jsonData []map[string]interface{}
+	if err := json.Unmarshal([]byte(body), &jsonData); err != nil {
+		fmt.Println("Error parsing JSON:", err)
+		return
+	}
+
+	// 处理每个组件
+	for i := range jsonData {
+		if err := processMapTable(jsonData[i], reportId, 0); err != nil {
+			fmt.Println("Error processing component:", err)
+			return
+		}
+	}
+
+	// 将处理后的数据转换回JSON字符串
+	//modifiedJSON, err := json.MarshalIndent(jsonData, "", "  ")
+	modifiedJSON, err := json.Marshal(jsonData)
+	if err != nil {
+		fmt.Println("Error marshaling JSON:", err)
+		return
+	}
+	newBody = string(modifiedJSON)
+
+	return
+}
+
+// HandleReportContentStructTableAndScene
+// @Description: 处理内容组件的表格链接,需要处理来源(跟另一个需求代码冲突了,不好处理,只能额外写个方法出来使用了)
+// @author: Roc
+// @datetime 2025-01-09 13:40:35
+// @param reportId int
+// @param body string
+// @return newBody string
+func HandleReportContentStructTableAndScene(reportId, fromScene int, body string) (newBody string) {
+	if body == `` {
+		return
+	}
+	newBody = body
+
+	// 解析JSON数据到map[string]interface{}
+	var jsonData []map[string]interface{}
+	if err := json.Unmarshal([]byte(body), &jsonData); err != nil {
+		fmt.Println("Error parsing JSON:", err)
+		return
+	}
+
+	// 处理每个组件
+	for i := range jsonData {
+		if err := processMapTable(jsonData[i], reportId, 0); err != nil {
+			fmt.Println("Error processing component:", err)
+			return
+		}
+	}
+
+	// 将处理后的数据转换回JSON字符串
+	modifiedJSON, err := json.MarshalIndent(jsonData, "", "  ")
+	if err != nil {
+		fmt.Println("Error marshaling JSON:", err)
+		return
+	}
+	newBody = string(modifiedJSON)
+
+	return
+}
+
+// processMapTable 递归处理map中的content字段
+func processMapTable(data map[string]interface{}, reportId, fromScene int) error {
+	for key, value := range data {
+		switch v := value.(type) {
+		case string:
+			if key == "content" {
+				contentSource, ok := data["compType"]
+				if !ok {
+					continue
+				}
+				contentSourceType, ok := contentSource.(string)
+				if !ok {
+					continue
+				}
+				if !utils.InArrayByStr([]string{`sheet`, `chart`}, contentSourceType) {
+					continue
+				}
+				newContent := handleTableLinkReportId(v, reportId, fromScene)
+				data[key] = newContent
+			}
+		case map[string]interface{}:
+			if err := processMapTable(v, reportId, fromScene); err != nil {
+				return err
+			}
+		case []interface{}:
+			for i := range v {
+				if m, ok := v[i].(map[string]interface{}); ok {
+					if err := processMapTable(m, reportId, fromScene); err != nil {
+						return err
+					}
+				}
+			}
+		}
+	}
+	return nil
+}

+ 7 - 0
utils/constants.go

@@ -450,6 +450,13 @@ const (
 	EdbClassifyTypeOrigin    = -1 // 指标分类-原(基础+计算)指标
 )
 
+const (
+	TableReferencedByReport   = 2 // 研报列表 与表格的关系
+	TableReferencedByEnReport = 3 // 英文研报 与表格的关系
+	TableReferencedByPPT      = 4 // PPT 与表格的关系
+	TableReferencedByEnPPT    = 5 // 英文PPT 与表格的关系
+)
+
 const (
 	EdbTypeBase      = 1 // 指标类型-基础指标
 	EdbTypeCalculate = 2 // 指标类型-计算指标