فهرست منبع

Merge branch 'master' into bugfix_7318_chart_pic_search

kobe6258 2 هفته پیش
والد
کامیت
66d2384070
35فایلهای تغییر یافته به همراه1164 افزوده شده و 258 حذف شده
  1. 36 23
      controllers/bi_dashboard.go
  2. 7 27
      controllers/data_manage/chart_info.go
  3. 10 37
      controllers/data_manage/edb_info.go
  4. 20 63
      controllers/data_manage/edb_info_calculate.go
  5. 119 10
      controllers/data_manage/excel/excel_info.go
  6. 2 2
      controllers/data_manage/future_good/future_good_profit_chart_info.go
  7. 31 0
      controllers/ppt_v2.go
  8. 7 0
      controllers/report_chapter.go
  9. 1 1
      controllers/report_history.go
  10. 10 0
      controllers/report_v2.go
  11. 3 1
      controllers/smart_report/smart_resource.go
  12. 3 0
      main.go
  13. 23 13
      models/ai_summary/ai_summary_classify.go
  14. 174 0
      models/data_manage/excel/referenced_excel_config.go
  15. 1 0
      models/data_manage/excel/request/excel_info.go
  16. 1 0
      models/data_manage/excel/request/mixed_table.go
  17. 11 10
      models/data_manage/excel/response/excel_info.go
  18. 1 1
      models/data_manage/multiple_graph_config_chart_mapping.go
  19. 9 6
      models/ppt_v2.go
  20. 48 26
      models/sandbox/sandbox_classify.go
  21. 2 0
      models/smart_report/smart_resource.go
  22. 9 0
      routers/commentsRouter.go
  23. 106 6
      services/data/chart_info.go
  24. 5 5
      services/data/correlation/chart_info.go
  25. 10 3
      services/data/edb_classify.go
  26. 100 0
      services/data/edb_info.go
  27. 5 5
      services/data/line_equation/chart_info.go
  28. 5 5
      services/data/line_feature/chart_info.go
  29. 5 5
      services/data/range_analysis/chart_info.go
  30. 3 0
      services/excel/lucky_sheet.go
  31. 90 6
      services/ppt.go
  32. 2 2
      services/report.go
  33. 296 0
      services/report_v2.go
  34. 2 1
      utils/common.go
  35. 7 0
      utils/constants.go

+ 36 - 23
controllers/bi_dashboard.go

@@ -660,36 +660,49 @@ func (this *BIDaShboardController) PublicList() {
 			GroupName: c.BiDashboardClassifyName,
 			Children:  make([]*bi_dashboard.RespPublicGroupListItem, 0),
 		}
-		if _, ok := publicDashboardClassifyIdMap[c.BiDashboardClassifyId]; ok {
-			for _, v := range adminIdList {
-				systemAdmin, ok := systemAdminMap[v]
-				if !ok {
-					continue
-				}
+		_, ok := publicDashboardClassifyIdMap[c.BiDashboardClassifyId]
+		if !ok {
+			continue
+		}
 
-				// 看板 列表信息
-				respGroupNameListItemList, ok := publicDashboardListMap[v]
-				if !ok {
-					respGroupNameListItemList = make([]*bi_dashboard.BiDashboard, 0)
-				}
+		tmpRespGroupIndexMap := make(map[int]int)
+		child := make([]*bi_dashboard.RespPublicGroupListItem, 0)
 
-				// ppt 分组信息
-				tmpRespGroupListItem := &bi_dashboard.RespPublicGroupListItem{
-					GroupId:       int64(systemAdmin.AdminId),
-					GroupName:     systemAdmin.RealName,
-					AdminId:       systemAdmin.AdminId,
-					DashboardList: make([]*bi_dashboard.BiDashboard, 0),
-				}
+		for _, v := range adminIdList {
+			systemAdmin, ok := systemAdminMap[v]
+			if !ok {
+				continue
+			}
+
+			// 看板 列表信息
+			respGroupNameListItemList, ok := publicDashboardListMap[v]
+			if !ok {
+				respGroupNameListItemList = make([]*bi_dashboard.BiDashboard, 0)
+			}
 
-				for _, vv := range respGroupNameListItemList {
-					if vv.BiDashboardClassifyId == c.BiDashboardClassifyId {
-						tmpRespGroupListItem.DashboardList = append(tmpRespGroupListItem.DashboardList, vv)
-						tmpItem.Children = append(tmpItem.Children, tmpRespGroupListItem)
+			for _, vv := range respGroupNameListItemList {
+				if vv.BiDashboardClassifyId == c.BiDashboardClassifyId {
+					tmpIndex, ok := tmpRespGroupIndexMap[systemAdmin.AdminId]
+					if !ok {
+						// 用户的分组信息
+						tmpRespGroupListItem := &bi_dashboard.RespPublicGroupListItem{
+							GroupId:       int64(systemAdmin.AdminId),
+							GroupName:     systemAdmin.RealName,
+							AdminId:       systemAdmin.AdminId,
+							DashboardList: make([]*bi_dashboard.BiDashboard, 0),
+						}
+						tmpIndex = len(child)
+						child = append(child, tmpRespGroupListItem)
+						tmpRespGroupIndexMap[systemAdmin.AdminId] = tmpIndex
 					}
+					tmpRespGroupListItem := child[tmpIndex]
+					child[tmpIndex].DashboardList = append(tmpRespGroupListItem.DashboardList, vv)
+					//tmpItem.Children = append(tmpItem.Children, tmpRespGroupListItem)
 				}
+				tmpItem.Children = child
 			}
-			resp = append(resp, tmpItem)
 		}
+		resp = append(resp, tmpItem)
 	}
 
 	br.Ret = 200

+ 7 - 27
controllers/data_manage/chart_info.go

@@ -552,8 +552,6 @@ func (this *ChartInfoController) ChartInfoBaseEdit() {
 		return
 	}
 
-	var edbCondition string
-	var edbPars []interface{}
 	for _, v := range req.ChartEdbInfoList {
 		edbInfoId := v.EdbInfoId
 		edbInfo, err := data_manage.GetEdbInfoById(edbInfoId)
@@ -574,34 +572,16 @@ func (this *ChartInfoController) ChartInfoBaseEdit() {
 			return
 		}
 
-		//判断指标名称是否重复
+		// 根据指标名称和指标ID校验库中是否还存在其他同名指标
 		if v.EdbName != "" {
-			edbCondition = ""
-			edbPars = make([]interface{}, 0)
-
-			edbCondition += " AND edb_info_id<>? "
-			edbPars = append(edbPars, edbInfo.EdbInfoId)
-
-			switch this.Lang {
-			case utils.EnLangVersion:
-				edbCondition += " AND edb_name_en =? "
-			default:
-				edbCondition += " AND edb_name =? "
-			}
-
-			edbPars = append(edbPars, v.EdbName)
-
-			edbExist, err := data_manage.GetEdbInfoByCondition(edbCondition, edbPars)
+			existEdbName, err := data.CheckExistByEdbNameAndEdbInfoId(utils.EDB_INFO_TYPE, edbInfo.EdbInfoId, this.SysUser.AdminId, v.EdbName, this.Lang)
 			if err != nil {
-				if !utils.IsErrNoRow(err) {
-					br.Msg = "判断英文指标名称是否存在失败"
-					br.ErrMsg = "判断英文指标名称是否存在失败,Err:" + err.Error()
-					return
-				}
+				br.Msg = "判断指标名称是否存在失败"
+				br.ErrMsg = "判断指标名称是否存在失败,Err:" + err.Error()
+				return
 			}
-
-			if err == nil && edbExist.EdbInfoId > 0 {
-				br.Msg = edbExist.EdbName + ":" + v.EdbName + "指标名称已存在"
+			if existEdbName {
+				br.Msg = v.EdbName + ":" + v.EdbName + "指标名称已存在"
 				br.ErrMsg = "指标名称已存在,请重新填写"
 				br.IsSendEmail = false
 				return

+ 10 - 37
controllers/data_manage/edb_info.go

@@ -916,27 +916,15 @@ func (this *EdbInfoController) EdbInfoEdit() {
 		return
 	}
 
-	//判断指标名称是否存在
-	var condition string
-	var pars []interface{}
-
-	condition += " AND edb_info_id<>? "
-	pars = append(pars, req.EdbInfoId)
-
-	//condition += " AND source=? "
-	//pars = append(pars, edbInfo.Source)
-
 	updateCols := make([]string, 0)
 	switch this.Lang {
 	case utils.EnLangVersion:
-		condition += " AND edb_name_en = ? "
 		edbInfo.EdbNameEn = req.EdbName
 		edbInfo.Frequency = req.Frequency
 		edbInfo.UnitEn = req.Unit
 		edbInfo.ClassifyId = req.ClassifyId
 		updateCols = append(updateCols, "EdbNameEn", "Frequency", "UnitEn", "ClassifyId")
 	default:
-		condition += " AND edb_name=? "
 		edbInfo.EdbName = req.EdbName
 		edbInfo.EdbNameSource = req.EdbName
 		edbInfo.Frequency = req.Frequency
@@ -944,16 +932,15 @@ func (this *EdbInfoController) EdbInfoEdit() {
 		edbInfo.ClassifyId = req.ClassifyId
 		updateCols = append(updateCols, "EdbName", "EdbNameSource", "Frequency", "Unit", "ClassifyId")
 	}
-	pars = append(pars, req.EdbName)
 
-	count, err := data_manage.GetEdbInfoCountByCondition(condition, pars)
+	// 根据指标名称和指标ID校验库中是否还存在其他同名指标
+	existEdbName, err := data.CheckExistByEdbNameAndEdbInfoId(utils.EDB_INFO_TYPE, req.EdbInfoId, this.SysUser.AdminId, req.EdbName, this.Lang)
 	if err != nil {
 		br.Msg = "判断指标名称是否存在失败"
 		br.ErrMsg = "判断指标名称是否存在失败,Err:" + err.Error()
 		return
 	}
-
-	if count > 0 {
+	if existEdbName {
 		br.Msg = "指标名称已存在,请重新填写"
 		br.ErrMsg = "指标名称已存在,请重新填写"
 		br.IsSendEmail = false
@@ -1197,44 +1184,30 @@ func (this *EdbInfoController) EdbInfoBaseEdit() {
 
 	if req.EdbName != "" {
 		//判断指标名称是否存在
-		var condition string
-		var pars []interface{}
-
-		condition += " AND edb_info_id<>? "
-		pars = append(pars, req.EdbInfoId)
-
-		/*condition += " AND source=? "
-		pars = append(pars, edbInfo.Source)*/
 
 		switch this.Lang {
 		case utils.EnLangVersion:
-			condition += " AND edb_name_en = ? "
 			edbInfo.EdbNameEn = req.EdbName
 			edbInfo.UnitEn = req.Unit
 			edbInfo.ModifyTime = time.Now()
 			updateCols = append(updateCols, "EdbNameEn", "UnitEn", "ModifyTime")
 		default:
-			condition += " AND edb_name = ? "
 			edbInfo.EdbName = req.EdbName
 			edbInfo.EdbNameSource = req.EdbName
 			edbInfo.Unit = req.Unit
 			edbInfo.ModifyTime = time.Now()
 			updateCols = append(updateCols, "EdbName", "EdbNameSource", "Unit", "ModifyTime")
 		}
-		pars = append(pars, req.EdbName)
 
-		edbExist, err := data_manage.GetEdbInfoByCondition(condition, pars)
+		existEdbName, err := data.CheckExistByEdbNameAndEdbInfoId(utils.EDB_INFO_TYPE, req.EdbInfoId, this.SysUser.AdminId, req.EdbName, this.Lang)
 		if err != nil {
-			if !utils.IsErrNoRow(err) {
-				br.Msg = "判断英文指标名称是否存在失败"
-				br.ErrMsg = "判断英文指标名称是否存在失败,Err:" + err.Error()
-				return
-			}
+			br.Msg = "判断指标名称是否存在失败"
+			br.ErrMsg = "判断指标名称是否存在失败,Err:" + err.Error()
+			return
 		}
-
-		if err == nil && edbExist.EdbInfoId > 0 {
-			br.Msg = edbExist.EdbName + ":" + req.EdbName + "指标名称已存在"
-			br.ErrMsg = "英文指标名称已存在,请重新填写"
+		if existEdbName {
+			br.Msg = "指标名称已存在,请重新填写"
+			br.ErrMsg = "指标名称已存在,请重新填写"
 			br.IsSendEmail = false
 			return
 		}

+ 20 - 63
controllers/data_manage/edb_info_calculate.go

@@ -113,24 +113,20 @@ func (this *ChartInfoController) CalculateSave() {
 		req.EdbInfoIdArr = newEdbInfoIdArr
 	}
 
-	var condition string
-	var pars []interface{}
-	condition += " AND edb_name=? "
-	pars = append(pars, req.EdbName)
-
-	count, err := data_manage.GetEdbInfoCountByCondition(condition, pars)
+	// 根据指标名称和指标ID校验库中是否还存在其他同名指标
+	existEdbName, err := data.CheckExistByEdbNameAndEdbInfoId(utils.EDB_INFO_TYPE, 0, this.SysUser.AdminId, req.EdbName, this.Lang)
 	if err != nil {
 		br.Msg = "判断指标名称是否存在失败"
 		br.ErrMsg = "判断指标名称是否存在失败,Err:" + err.Error()
 		return
 	}
-
-	if count > 0 {
+	if existEdbName {
 		br.Msg = "指标名称已存在,请重新填写"
 		br.ErrMsg = "指标名称已存在,请重新填写"
 		br.IsSendEmail = false
 		return
 	}
+
 	//检验公式
 	var formulaStr string
 	var edbInfoIdBytes []string
@@ -419,22 +415,14 @@ func (this *ChartInfoController) CalculateEdit() {
 		req.EdbInfoIdArr = newEdbInfoIdArr
 	}
 
-	var condition string
-	var pars []interface{}
-	condition += " AND edb_name=? "
-	pars = append(pars, req.EdbName)
-
-	condition += " AND edb_info_id<>? "
-	pars = append(pars, req.EdbInfoId)
-
-	count, err := data_manage.GetEdbInfoCountByCondition(condition, pars)
+	// 根据指标名称和指标ID校验库中是否还存在其他同名指标
+	existEdbName, err := data.CheckExistByEdbNameAndEdbInfoId(utils.EDB_INFO_TYPE, req.EdbInfoId, this.SysUser.AdminId, req.EdbName, this.Lang)
 	if err != nil {
 		br.Msg = "判断指标名称是否存在失败"
 		br.ErrMsg = "判断指标名称是否存在失败,Err:" + err.Error()
 		return
 	}
-
-	if count > 0 {
+	if existEdbName {
 		br.Msg = "指标名称已存在,请重新填写"
 		br.ErrMsg = "指标名称已存在,请重新填写"
 		br.IsSendEmail = false
@@ -751,22 +739,14 @@ func (this *ChartInfoController) CalculateBatchEdit() {
 		return
 	}
 
-	var condition string
-	var pars []interface{}
-	condition += " AND edb_name=? "
-	pars = append(pars, req.EdbName)
-
-	condition += " AND edb_info_id<>? "
-	pars = append(pars, req.EdbInfoId)
-
-	count, err := data_manage.GetEdbInfoCountByCondition(condition, pars)
+	// 根据指标名称和指标ID校验库中是否还存在其他同名指标
+	existEdbName, err := data.CheckExistByEdbNameAndEdbInfoId(utils.EDB_INFO_TYPE, req.EdbInfoId, this.SysUser.AdminId, req.EdbName, this.Lang)
 	if err != nil {
 		br.Msg = "判断指标名称是否存在失败"
 		br.ErrMsg = "判断指标名称是否存在失败,Err:" + err.Error()
 		return
 	}
-
-	if count > 0 {
+	if existEdbName {
 		br.Msg = "指标名称已存在,请重新填写"
 		br.ErrMsg = "指标名称已存在,请重新填写"
 		br.IsSendEmail = false
@@ -1158,23 +1138,16 @@ func (this *ChartInfoController) AddPythonEdb() {
 		br.ErrMsg = "参数解析失败,Err:" + err.Error()
 		return
 	}
-	// 判断指标名称是否重复
-	{
-		var condition string
-		var pars []interface{}
-		condition += " AND edb_name=? "
-		pars = append(pars, req.EdbName)
 
-		condition += " AND edb_info_id<>? "
-		pars = append(pars, req.EdbInfoId)
-
-		count, err := data_manage.GetEdbInfoCountByCondition(condition, pars)
+	// 根据指标名称和指标ID校验库中是否还存在其他同名指标
+	{
+		existEdbName, err := data.CheckExistByEdbNameAndEdbInfoId(utils.EDB_INFO_TYPE, req.EdbInfoId, this.SysUser.AdminId, req.EdbName, this.Lang)
 		if err != nil {
 			br.Msg = "判断指标名称是否存在失败"
 			br.ErrMsg = "判断指标名称是否存在失败,Err:" + err.Error()
 			return
 		}
-		if count > 0 {
+		if existEdbName {
 			br.Msg = "指标名称已存在,请重新填写"
 			br.ErrMsg = "指标名称已存在,请重新填写"
 			br.IsSendEmail = false
@@ -1262,23 +1235,15 @@ func (this *ChartInfoController) EditPythonEdb() {
 		return
 	}
 
-	// 判断指标名称是否重复
+	// 根据指标名称和指标ID校验库中是否还存在其他同名指标
 	{
-		var condition string
-		var pars []interface{}
-		condition += " AND edb_name=? "
-		pars = append(pars, req.EdbName)
-
-		condition += " AND edb_info_id<>? "
-		pars = append(pars, req.EdbInfoId)
-
-		count, err := data_manage.GetEdbInfoCountByCondition(condition, pars)
+		existEdbName, err := data.CheckExistByEdbNameAndEdbInfoId(utils.EDB_INFO_TYPE, req.EdbInfoId, this.SysUser.AdminId, req.EdbName, this.Lang)
 		if err != nil {
 			br.Msg = "判断指标名称是否存在失败"
 			br.ErrMsg = "判断指标名称是否存在失败,Err:" + err.Error()
 			return
 		}
-		if count > 0 {
+		if existEdbName {
 			br.Msg = "指标名称已存在,请重新填写"
 			br.ErrMsg = "指标名称已存在,请重新填写"
 			br.IsSendEmail = false
@@ -1467,23 +1432,15 @@ func (this *ChartInfoController) SaveAdjustEdbInfo() {
 		br.ErrMsg = "参数解析失败,Err:" + err.Error()
 		return
 	}
-	// 判断指标名称是否重复
+	// 根据指标名称和指标ID校验库中是否还存在其他同名指标
 	{
-		var condition string
-		var pars []interface{}
-		condition += " AND edb_name=? "
-		pars = append(pars, req.EdbName)
-
-		condition += " AND edb_info_id<>? "
-		pars = append(pars, req.EdbInfoId)
-
-		count, err := data_manage.GetEdbInfoCountByCondition(condition, pars)
+		existEdbName, err := data.CheckExistByEdbNameAndEdbInfoId(utils.EDB_INFO_TYPE, req.EdbInfoId, this.SysUser.AdminId, req.EdbName, this.Lang)
 		if err != nil {
 			br.Msg = "判断指标名称是否存在失败"
 			br.ErrMsg = "判断指标名称是否存在失败,Err:" + err.Error()
 			return
 		}
-		if count > 0 {
+		if existEdbName {
 			br.Msg = "指标名称已存在,请重新填写"
 			br.ErrMsg = "指标名称已存在,请重新填写"
 			br.IsSendEmail = false

+ 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 && !utils.IsErrNoRow(err) {
+		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 && !utils.IsErrNoRow(e) {
+		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 && !utils.IsErrNoRow(err) {
+			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
+}

+ 2 - 2
controllers/data_manage/future_good/future_good_profit_chart_info.go

@@ -742,8 +742,8 @@ func copyProfitChartInfo(oldChartInfo *data_manage.ChartInfo, chartClassifyId in
 	condition += " AND chart_classify_id=? "
 	pars = append(pars, chartClassifyId)
 
-	condition += " AND chart_name=? AND source = ? "
-	pars = append(pars, chartName, utils.CHART_SOURCE_FUTURE_GOOD_PROFIT)
+	condition += " AND chart_name=? AND source = ?  AND sys_user_id = ? "
+	pars = append(pars, chartName, utils.CHART_SOURCE_FUTURE_GOOD_PROFIT, sysUser.AdminId)
 
 	count, err := data_manage.GetChartInfoCountByCondition(condition, pars)
 	if err != nil {

+ 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)

+ 1 - 1
controllers/report_history.go

@@ -196,7 +196,7 @@ func (this *ReportHistoryController) Detail() {
 	if reportInfo.HasChapter == 1 && reportChapterId > 0 {
 		chapter, e := models.GetReportChapterInfoById(reportChapterId)
 		if e != nil {
-			if e.Error() == utils.ErrNoRow() {
+			if utils.IsErrNoRow(e) {
 				br.Msg = "章节已删除"
 				return
 			}

+ 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,

+ 3 - 1
controllers/smart_report/smart_resource.go

@@ -167,7 +167,9 @@ func (this *SmartReportResourceController) Edit() {
 		return
 	}
 
-	cols := []string{"ImgName", "Style"}
+	cols := []string{"Type", "ImgUrl", "ImgName", "Style"}
+	item.Type = req.Type
+	item.ImgUrl = req.ImgUrl
 	item.ImgName = req.ImgName
 	item.Style = req.Style
 

+ 3 - 0
main.go

@@ -23,6 +23,9 @@ func main() {
 		web.BConfig.WebConfig.DirectoryIndex = true
 		web.BConfig.WebConfig.StaticDir["/swagger"] = "swagger"
 	}
+	// 服务名称
+	web.BConfig.ServerName = `server`
+
 	go services.Task()
 
 	// 初始化表数据入库

+ 23 - 13
models/ai_summary/ai_summary_classify.go

@@ -148,19 +148,29 @@ type AiSummaryClassifyDeleteCheckReq struct {
 }
 
 func GetAiSummaryInfoCountByClassifyId(classifyId int) (count int, err error) {
-	sql := ` SELECT COUNT(1) AS count FROM ai_summary AS a
-				WHERE a.classify_id IN(
-				SELECT t.ai_summary_classify_id FROM 
-				(
-				SELECT rd.*
-				FROM (SELECT * FROM ai_summary_classify WHERE parent_id IS NOT NULL) rd,
-					 (SELECT @pid := ?) pd 
-				WHERE FIND_IN_SET(parent_id, @pid) > 0 
-				  AND @pid := CONCAT(@pid, ',', ai_summary_classify_id) 
-				UNION SELECT * FROM ai_summary_classify WHERE ai_summary_classify_id = @pid 
-				)AS t
-				) `
-	err = global.DEFAULT_DmSQL.Raw(sql, classifyId).Scan(&count).Error
+	var pars []interface{}
+	var sql string
+	sql = `WITH RECURSIVE ai_summary_classify_cte (ai_summary_classify_id, parent_id) AS (
+				SELECT ai_summary_classify_id, parent_id
+				FROM ai_summary_classify
+				WHERE parent_id = ?
+				UNION ALL
+				SELECT c.ai_summary_classify_id, c.parent_id
+				FROM ai_summary_classify c
+				INNER JOIN ai_summary_classify_cte ct ON c.parent_id = ct.ai_summary_classify_id
+			)
+			SELECT COUNT(1) AS count
+			FROM ai_summary a
+			WHERE a.classify_id IN (
+				SELECT ai_summary_classify_id
+				FROM ai_summary_classify_cte
+				UNION
+				SELECT ai_summary_classify_id
+				FROM ai_summary_classify
+				WHERE ai_summary_classify_id = ?
+			)`
+	pars = append(pars, classifyId, classifyId)
+	err = global.DEFAULT_DmSQL.Raw(sql, pars...).Scan(&count).Error
 	return
 }
 

+ 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       `gorm:"column:referenced_excel_config_id;primaryKey;" ` // 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

+ 1 - 1
models/data_manage/multiple_graph_config_chart_mapping.go

@@ -166,7 +166,7 @@ func ReplaceMultipleGraphConfigChartEdb(oldEdbInfo, newEdbInfo *EdbInfo, userId
 		tmpChartInfoCorrelationList := make([]*ChartInfoCorrelation, 0)
 		tmpSql := `SELECT a.* FROM chart_info_correlation AS a 
          JOIN chart_info AS b on a.correlation_chart_info_id = b.chart_info_id
-         WHERE b.sys_user_id = ? AND (edb_info_id_a=? or edb_info_id_b=?) `
+         WHERE b.sys_user_id = ? AND (edb_info_id_first=? or edb_info_id_second=?) `
 		err = to.Raw(tmpSql, userId, oldEdbInfo.EdbInfoId, oldEdbInfo.EdbInfoId).Find(&tmpChartInfoCorrelationList).Error
 		if err != nil {
 			errmsg = "获取指标关联图表配置信息失败:Err:" + err.Error()

+ 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 {

+ 48 - 26
models/sandbox/sandbox_classify.go

@@ -106,19 +106,31 @@ type SandboxClassifyDeleteCheckReq struct {
 }
 
 func GetSandboxInfoCountByClassifyId(classifyId int) (count int, err error) {
-	sql := ` SELECT COUNT(1) AS count FROM sandbox AS a
-				WHERE a.sandbox_classify_id IN(
-				SELECT t.sandbox_classify_id FROM 
-				(
-				SELECT rd.*
-				FROM (SELECT * FROM sandbox_classify WHERE parent_id IS NOT NULL) rd,
-					 (SELECT @pid := ?) pd 
-				WHERE FIND_IN_SET(parent_id, @pid) > 0 
-				  AND @pid := CONCAT(@pid, ',', sandbox_classify_id) 
-				UNION SELECT * FROM sandbox_classify WHERE sandbox_classify_id = @pid 
-				)AS t
-				) AND a.is_delete = 0 `
-	err = global.DmSQL["data"].Raw(sql, classifyId).Scan(&count).Error
+	var sql string
+	var pars []interface{}
+	sql = `WITH RECURSIVE classify_tree (sandbox_classify_id, parent_id, level) AS (
+    -- 基础查询:获取起始节点
+    SELECT sandbox_classify_id, parent_id, 1 as level
+    FROM sandbox_classify
+    WHERE sandbox_classify_id = ?
+    
+    UNION ALL
+    
+    -- 递归查询:获取所有子节点
+    SELECT c.sandbox_classify_id, c.parent_id, t.level + 1
+    FROM sandbox_classify c
+    INNER JOIN classify_tree t ON c.parent_id = t.sandbox_classify_id
+    WHERE c.parent_id IS NOT NULL
+)
+SELECT COUNT(1) AS count 
+FROM sandbox a
+WHERE a.sandbox_classify_id IN (
+    SELECT sandbox_classify_id 
+    FROM classify_tree
+) 
+AND a.is_delete = 0`
+	pars = append(pars, classifyId, classifyId)
+	err = global.DmSQL["data"].Raw(sql, pars...).Scan(&count).Error
 	return
 }
 
@@ -133,19 +145,29 @@ type DeleteSandboxClassifyReq struct {
 }
 
 func DeleteSandboxClassify(classifyId int) (err error) {
-	sql := ` DELETE FROM sandbox_classify
-				WHERE sandbox_classify_id IN(
-				SELECT t.sandbox_classify_id FROM
-				(
-				SELECT rd.*
-				FROM (SELECT * FROM sandbox_classify WHERE parent_id IS NOT NULL) rd,
-				(SELECT @pid := ?) pd
-				WHERE FIND_IN_SET(parent_id, @pid) > 0
-				AND @pid := CONCAT(@pid, ',', sandbox_classify_id)
-				UNION SELECT * FROM sandbox_classify WHERE sandbox_classify_id = @pid
-				)AS t
-				) `
-	err = global.DmSQL["data"].Exec(sql, classifyId).Error
+	var pars []interface{}
+	var sql string
+	sql = `WITH RECURSIVE sandbox_classify_cte (sandbox_classify_id, parent_id) AS (
+			SELECT sandbox_classify_id, parent_id
+			FROM sandbox_classify
+			WHERE parent_id = ?
+			UNION ALL
+			SELECT c.sandbox_classify_id, c.parent_id
+			FROM sandbox_classify c
+			INNER JOIN sandbox_classify_cte ct ON c.parent_id = ct.sandbox_classify_id
+		)
+		DELETE FROM sandbox_classify
+		WHERE sandbox_classify_id IN (
+			SELECT sandbox_classify_id
+			FROM sandbox_classify_cte
+			UNION
+			SELECT sandbox_classify_id
+			FROM sandbox_classify
+			WHERE sandbox_classify_id = ?
+		)`
+	pars = append(pars, classifyId, classifyId)
+	err = global.DmSQL["data"].Exec(sql, pars...).Error
+
 	return
 }
 

+ 2 - 0
models/smart_report/smart_resource.go

@@ -107,6 +107,8 @@ func (m *SmartReportResource) GetItemsByCondition(condition string, pars []inter
 // SmartReportResourceEditReq 智能研报资源编辑请求体
 type SmartReportResourceEditReq struct {
 	ResourceId int    `description:"资源ID"`
+	Type       int    `description:"类型 1-版头 2-版尾"`
+	ImgUrl     string `description:"图片资源地址"`
 	ImgName    string `description:"图片名称"`
 	Style      string `description:"版图样式"`
 }

+ 9 - 0
routers/commentsRouter.go

@@ -1483,6 +1483,15 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage/excel:ExcelInfoController"] = append(beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage/excel:ExcelInfoController"],
+        beego.ControllerComments{
+            Method: "SaveExcelReference",
+            Router: `/excel_info/reference/save`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage/excel:ExcelInfoController"] = append(beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage/excel:ExcelInfoController"],
         beego.ControllerComments{
             Method: "Rename",

+ 106 - 6
services/data/chart_info.go

@@ -2224,11 +2224,11 @@ func AddChartInfo(req data_manage.AddChartInfoReq, sysUserId int, sysUserRealNam
 
 		switch lang {
 		case utils.EnLangVersion:
-			condition += " AND chart_name_en = ? AND source = ? "
+			condition += " AND chart_name_en = ? AND source = ? AND sys_user_id = ? "
 		default:
-			condition += " AND chart_name = ? AND source = ? "
+			condition += " AND chart_name = ? AND source = ? AND sys_user_id = ? "
 		}
-		pars = append(pars, req.ChartName, utils.CHART_SOURCE_DEFAULT)
+		pars = append(pars, req.ChartName, utils.CHART_SOURCE_DEFAULT, sysUserId)
 
 		count, err = data_manage.GetChartInfoCountByCondition(condition, pars)
 		if err != nil {
@@ -2661,11 +2661,11 @@ func EditChartInfo(req data_manage.EditChartInfoReq, sysUser *system.Admin, lang
 
 		switch lang {
 		case utils.EnLangVersion:
-			condition += " AND chart_name_en = ? AND source = ? "
+			condition += " AND chart_name_en = ? AND source = ? AND sys_user_id = ? "
 		default:
-			condition += " AND chart_name = ? AND source = ? "
+			condition += " AND chart_name = ? AND source = ? AND sys_user_id = ? "
 		}
-		pars = append(pars, req.ChartName, utils.CHART_SOURCE_DEFAULT)
+		pars = append(pars, req.ChartName, utils.CHART_SOURCE_DEFAULT, sysUser.AdminId)
 
 		count, err = data_manage.GetChartInfoCountByCondition(condition, pars)
 		if err != nil {
@@ -5034,3 +5034,103 @@ func CheckChartReferencedByOthers(chartInfoIdList []int, chartUniqueCodeList []s
 	noReferenced = true
 	return
 }
+
+// CheckExistByEdbNameAndEdbInfoId
+// @Description: 根据指标名称和指标ID校验库中是否还存在其他同名指标
+// @author: Roc
+// @datetime 2024-04-18 15:01:44
+// @param chartInfoType int
+// @param chartInfoId int
+// @param chartName string
+// @param lang string
+// @return has bool
+// @return err error
+func CheckExistByChartNameAndChartInfoId(source, chartInfoId, userId int, chartName, lang string) (has bool, err error) {
+	// 指标没有入库的情况
+	if chartInfoId == 0 {
+		return checkExistByChartName(source, userId, chartName, lang)
+	}
+
+	//指标已经入库的情况
+	return checkExistByChartNameAndChartInfoId(source, userId, chartInfoId, chartName, lang)
+}
+
+// checkExistByChartName
+// @Description: 根据指标名称校验该指标是否存在库中
+// @author: Roc
+// @datetime 2024-04-18 14:58:52
+// @param source int
+// @param chartName string
+// @param lang string
+// @return has bool
+// @return err error
+func checkExistByChartName(source, userId int, chartName, lang string) (has bool, err error) {
+	var condition string
+	var pars []interface{}
+
+	condition += " AND source=? AND sys_user_id=? "
+	pars = append(pars, source, userId)
+
+	switch lang {
+	case utils.EnLangVersion:
+		condition += " AND chart_name_en = ? "
+	default:
+		condition += " AND chart_name=? "
+	}
+
+	pars = append(pars, chartName)
+
+	count, err := data_manage.GetChartInfoCountByCondition(condition, pars)
+	if err != nil {
+		return
+	}
+
+	if count > 0 {
+		has = true
+		return
+	}
+
+	return
+}
+
+// checkExistByChartNameAndChartInfoId
+// @Description: 根据指标名称和指标ID校验库中是否还存在其他同名指标
+// @author: Roc
+// @datetime 2024-04-18 15:00:19
+// @param source int
+// @param chartInfoId int
+// @param chartName string
+// @param lang string
+// @return has bool
+// @return err error
+func checkExistByChartNameAndChartInfoId(source, userId, chartInfoId int, chartName, lang string) (has bool, err error) {
+	var condition string
+	var pars []interface{}
+
+	condition += " AND source=? AND sys_user_id=? "
+	pars = append(pars, source, userId)
+
+	condition += " AND chart_info_id<>? "
+	pars = append(pars, chartInfoId)
+
+	switch lang {
+	case utils.EnLangVersion:
+		condition += " AND chart_name_en = ? "
+	default:
+		condition += " AND chart_name=? "
+	}
+
+	pars = append(pars, chartName)
+
+	count, err := data_manage.GetChartInfoCountByCondition(condition, pars)
+	if err != nil {
+		return
+	}
+
+	if count > 0 {
+		has = true
+		return
+	}
+
+	return
+}

+ 5 - 5
services/data/correlation/chart_info.go

@@ -782,11 +782,11 @@ func AddChartInfo(req data_manage.AddChartInfoReq, source int, sysUser *system.A
 
 		switch lang {
 		case utils.EnLangVersion:
-			condition += " AND chart_name_en = ? AND source = ? "
+			condition += " AND chart_name_en = ? AND source = ? AND sys_user_id = ? "
 		default:
-			condition += " AND chart_name=? AND source = ? "
+			condition += " AND chart_name=? AND source = ? AND sys_user_id = ? "
 		}
-		pars = append(pars, req.ChartName, source)
+		pars = append(pars, req.ChartName, source, sysUser.AdminId)
 		count, tmpErr := data_manage.GetChartInfoCountByCondition(condition, pars)
 		if tmpErr != nil {
 			errMsg = "判断图表名称是否存在失败"
@@ -1034,8 +1034,8 @@ func EditChartInfo(req data_manage.EditChartInfoReq, sysUser *system.Admin, lang
 	{
 		var condition string
 		var pars []interface{}
-		condition += " AND chart_info_id <> ? "
-		pars = append(pars, req.ChartInfoId)
+		condition += " AND chart_info_id <> ? AND sys_user_id = ? "
+		pars = append(pars, req.ChartInfoId, sysUser.AdminId)
 		switch lang {
 		case utils.EnLangVersion:
 			condition += " AND chart_name_en = ? AND source = ? "

+ 10 - 3
services/data/edb_classify.go

@@ -1107,7 +1107,7 @@ func MoveEdbClassify(req data_manage.MoveEdbClassifyReq, sysUser *system.Admin,
 			err = errors.New("获取分类信息失败,Err:" + err.Error())
 			return
 		}
-		if edbClassifyInfo.SysUserId != sysUser.AdminId {
+		if edbClassifyInfo.ClassifyType != utils.EdbClassifyTypeBase && edbClassifyInfo.SysUserId != sysUser.AdminId {
 			errMsg = "不是本人目录,您没有操作权限"
 			err = errors.New(errMsg)
 			return
@@ -1567,8 +1567,15 @@ func moveEdbClassify(parentEdbClassifyInfo, edbClassifyInfo, prevClassify, nextC
 
 	oldClassifyIdPath := edbClassifyInfo.ClassifyIdPath
 	oldClassifyNamePath := edbClassifyInfo.ClassifyNamePath
-	newClassifyNamePath := fmt.Sprint(parentEdbClassifyInfo.ClassifyNamePath, `|`, edbClassifyInfo.ClassifyName)
-	newClassifyIdPath := fmt.Sprint(parentEdbClassifyInfo.ClassifyIdPath, `,`, edbClassifyInfo.ClassifyId)
+
+	newClassifyIdPath := oldClassifyIdPath
+	newClassifyNamePath := oldClassifyNamePath
+
+	// 如果不是一级的话,那么就需要更新路径
+	if parentEdbClassifyInfo != nil {
+		newClassifyIdPath = fmt.Sprint(parentEdbClassifyInfo.ClassifyIdPath, `,`, edbClassifyInfo.ClassifyId)
+		newClassifyNamePath = fmt.Sprint(parentEdbClassifyInfo.ClassifyNamePath, `|`, edbClassifyInfo.ClassifyName)
+	}
 
 	//更新
 	if len(updateCol) > 0 {

+ 100 - 0
services/data/edb_info.go

@@ -2137,3 +2137,103 @@ func CheckEdbReferencedByOthers(edbInfoType int, edbInfoIdList, belongUserIdList
 	noReferenced = true
 	return
 }
+
+// CheckExistByEdbNameAndEdbInfoId
+// @Description: 根据指标名称和指标ID校验库中是否还存在其他同名指标
+// @author: Roc
+// @datetime 2024-04-18 15:01:44
+// @param edbInfoType int
+// @param edbInfoId int
+// @param edbName string
+// @param lang string
+// @return has bool
+// @return err error
+func CheckExistByEdbNameAndEdbInfoId(edbInfoType, edbInfoId, userId int, edbName, lang string) (has bool, err error) {
+	// 指标没有入库的情况
+	if edbInfoId == 0 {
+		return checkExistByEdbName(edbInfoType, userId, edbName, lang)
+	}
+
+	//指标已经入库的情况
+	return checkExistByEdbNameAndEdbInfoId(edbInfoType, userId, edbInfoId, edbName, lang)
+}
+
+// checkExistByEdbName
+// @Description: 根据指标名称校验该指标是否存在库中
+// @author: Roc
+// @datetime 2024-04-18 14:58:52
+// @param edbInfoType int
+// @param edbName string
+// @param lang string
+// @return has bool
+// @return err error
+func checkExistByEdbName(edbInfoType, userId int, edbName, lang string) (has bool, err error) {
+	var condition string
+	var pars []interface{}
+
+	condition += " AND edb_info_type=? AND sys_user_id=? "
+	pars = append(pars, edbInfoType, userId)
+
+	switch lang {
+	case utils.EnLangVersion:
+		condition += " AND edb_name_en = ? "
+	default:
+		condition += " AND edb_name=? "
+	}
+
+	pars = append(pars, edbName)
+
+	count, err := data_manage.GetEdbInfoCountByCondition(condition, pars)
+	if err != nil {
+		return
+	}
+
+	if count > 0 {
+		has = true
+		return
+	}
+
+	return
+}
+
+// checkExistByEdbNameAndEdbInfoId
+// @Description: 根据指标名称和指标ID校验库中是否还存在其他同名指标
+// @author: Roc
+// @datetime 2024-04-18 15:00:19
+// @param edbInfoType int
+// @param edbInfoId int
+// @param edbName string
+// @param lang string
+// @return has bool
+// @return err error
+func checkExistByEdbNameAndEdbInfoId(edbInfoType, userId, edbInfoId int, edbName, lang string) (has bool, err error) {
+	var condition string
+	var pars []interface{}
+
+	condition += " AND edb_info_type=? AND sys_user_id=? "
+	pars = append(pars, edbInfoType, userId)
+
+	condition += " AND edb_info_id<>? "
+	pars = append(pars, edbInfoId)
+
+	switch lang {
+	case utils.EnLangVersion:
+		condition += " AND edb_name_en = ? "
+	default:
+		condition += " AND edb_name=? "
+	}
+
+	pars = append(pars, edbName)
+
+	count, err := data_manage.GetEdbInfoCountByCondition(condition, pars)
+	if err != nil {
+		return
+	}
+
+	if count > 0 {
+		has = true
+		return
+	}
+
+	return
+}

+ 5 - 5
services/data/line_equation/chart_info.go

@@ -411,11 +411,11 @@ func BatchAddChartInfo(batchAddChartReq []request.AddChart, lineChartInfoConfig
 			var pars []interface{}
 			switch lang {
 			case utils.EnLangVersion:
-				condition += " AND chart_name_en = ? AND source = ? "
+				condition += " AND chart_name_en = ? AND source = ? AND sys_user_id = ? "
 			default:
-				condition += " AND chart_name = ? AND source = ? "
+				condition += " AND chart_name = ? AND source = ? AND sys_user_id = ?  "
 			}
-			pars = append(pars, v.ChartName, source)
+			pars = append(pars, v.ChartName, source, sysUser.AdminId)
 			count, tmpErr := data_manage.GetChartInfoCountByCondition(condition, pars)
 			if tmpErr != nil {
 				errMsg = "判断图表名称是否存在失败"
@@ -631,8 +631,8 @@ func BatchSaveChartInfo(multipleGraphConfigId int, batchAddChartReq []request.Ad
 		// 判断图表是否存在
 		var condition string
 		var pars []interface{}
-		condition += " AND chart_name=? AND source = ? "
-		pars = append(pars, v.ChartName, source)
+		condition += " AND chart_name=? AND source = ?  AND sys_user_id = ? "
+		pars = append(pars, v.ChartName, source, sysUser.AdminId)
 
 		// 已经创建了图表的类型
 		if sourceChart, ok := existChartInfoMap[v.Source]; ok {

+ 5 - 5
services/data/line_feature/chart_info.go

@@ -460,11 +460,11 @@ func AddChartInfo(req data_manage.AddChartInfoReq, edbInfoMapping *data_manage.C
 
 		switch lang {
 		case utils.EnLangVersion:
-			condition += " AND chart_name_en = ? AND source = ? "
+			condition += " AND chart_name_en = ? AND source = ? AND sys_user_id = ? "
 		default:
-			condition += " AND chart_name = ? AND source = ? "
+			condition += " AND chart_name = ? AND source = ? AND sys_user_id = ? "
 		}
-		pars = append(pars, req.ChartName, source)
+		pars = append(pars, req.ChartName, source, sysUser.AdminId)
 		count, tmpErr := data_manage.GetChartInfoCountByCondition(condition, pars)
 		if tmpErr != nil {
 			errMsg = "判断图表名称是否存在失败"
@@ -610,8 +610,8 @@ func EditChartInfo(req data_manage.EditChartInfoReq, edbInfoMapping *data_manage
 	{
 		var condition string
 		var pars []interface{}
-		condition += " AND chart_info_id <> ? AND source = ?  "
-		pars = append(pars, req.ChartInfoId, chartItem.Source)
+		condition += " AND chart_info_id <> ? AND source = ? AND sys_user_id = ?  "
+		pars = append(pars, req.ChartInfoId, chartItem.Source, sysUser.AdminId)
 
 		switch lang {
 		case utils.EnLangVersion:

+ 5 - 5
services/data/range_analysis/chart_info.go

@@ -1096,11 +1096,11 @@ func AddChartInfo(req data_manage.AddChartInfoReq, source int, sysUser *system.A
 
 		switch lang {
 		case utils.EnLangVersion:
-			condition += " AND chart_name_en = ? AND source = ? "
+			condition += " AND chart_name_en = ? AND source = ? AND sys_user_id = ? "
 		default:
-			condition += " AND chart_name=? AND source = ? "
+			condition += " AND chart_name=? AND source = ? AND sys_user_id = ? "
 		}
-		pars = append(pars, req.ChartName, source)
+		pars = append(pars, req.ChartName, source, sysUser.AdminId)
 		count, tmpErr := data_manage.GetChartInfoCountByCondition(condition, pars)
 		if tmpErr != nil {
 			errMsg = "判断图表名称是否存在失败"
@@ -1355,8 +1355,8 @@ func EditChartInfo(req data_manage.EditChartInfoReq, sysUser *system.Admin, lang
 	{
 		var condition string
 		var pars []interface{}
-		condition += " AND chart_info_id <> ? "
-		pars = append(pars, req.ChartInfoId)
+		condition += " AND chart_info_id <> ? AND sys_user_id = ? "
+		pars = append(pars, req.ChartInfoId, sysUser.AdminId)
 		switch lang {
 		case utils.EnLangVersion:
 			condition += " AND chart_name_en = ? AND source = ? "

+ 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
+}

+ 2 - 1
utils/common.go

@@ -231,7 +231,8 @@ func StrListToString(strList []string) (str string) {
 
 // 数据没有记录
 func ErrNoRow() string {
-	return "<QuerySeter> no row found"
+	return gorm.ErrRecordNotFound.Error()
+	//return "<QuerySeter> no row found"
 }
 
 // IsErrNoRow

+ 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 // 指标类型-计算指标