Forráskód Böngészése

Merge branch 'master' into feature/eta1.9.1_edb_refresh

# Conflicts:
#	models/data_manage/edb_info.go
#	models/sandbox/sandbox.go
#	services/sandbox/sandbox.go
xyxie 10 hónapja
szülő
commit
f1dc9b27df
49 módosított fájl, 2668 hozzáadás és 172 törlés
  1. 22 0
      cache/replace_edb_info.go
  2. 10 10
      controllers/classify.go
  3. 599 0
      controllers/data_manage/ccf_data.go
  4. 18 2
      controllers/data_manage/chart_info.go
  5. 9 2
      controllers/data_manage/edb_classify.go
  6. 71 40
      controllers/data_manage/edb_info.go
  7. 18 2
      controllers/data_manage/excel/excel_info.go
  8. 3 2
      controllers/data_manage/predict_edb_classify.go
  9. 15 3
      controllers/ppt_english.go
  10. 15 3
      controllers/ppt_v2.go
  11. 4 4
      controllers/report.go
  12. 26 4
      controllers/sandbox/sandbox.go
  13. 2 2
      controllers/smart_report/smart_report.go
  14. 144 0
      models/data_manage/base_from_ccf.go
  15. 55 0
      models/data_manage/base_from_ccf_classify.go
  16. 155 0
      models/data_manage/ccf_stock_classify.go
  17. 171 0
      models/data_manage/ccf_stock_excel.go
  18. 9 0
      models/data_manage/chart_edb_mapping.go
  19. 4 4
      models/data_manage/chart_info.go
  20. 16 0
      models/data_manage/cross_variety/chart_info_cross_variety.go
  21. 11 0
      models/data_manage/cross_variety/chart_tag_variety.go
  22. 13 3
      models/data_manage/edb_classify.go
  23. 138 1
      models/data_manage/edb_info.go
  24. 32 2
      models/data_manage/excel/excel_edb_mapping.go
  25. 74 4
      models/data_manage/excel/excel_info.go
  26. 40 0
      models/data_manage/excel/request/time_table.go
  27. 126 0
      models/data_manage/multiple_graph_config.go
  28. 136 0
      models/data_manage/multiple_graph_config_chart_mapping.go
  29. 2 2
      models/data_manage/my_chart.go
  30. 14 13
      models/permission.go
  31. 8 0
      models/ppt_english/ppt_english_group_mapping.go
  32. 8 0
      models/ppt_v2_group_mapping.go
  33. 2 2
      models/report.go
  34. 26 0
      models/sandbox/sandbox.go
  35. 12 5
      models/sandbox/sandbox_classify.go
  36. 63 0
      routers/commentsRouter.go
  37. 10 8
      services/chart_permission_sync.go
  38. 24 9
      services/data/chart_info.go
  39. 88 16
      services/data/edb_classify.go
  40. 30 18
      services/data/edb_info.go
  41. 105 0
      services/data/edb_refresh.go
  42. 2 2
      services/data/excel/excel_info.go
  43. 254 0
      services/edb_info_replace.go
  44. 3 3
      services/report.go
  45. 3 3
      services/report_classify.go
  46. 63 0
      services/sandbox/sandbox.go
  47. 5 2
      services/task.go
  48. 8 1
      static/ErrMsgConfig.json
  49. 2 0
      utils/constants.go

+ 22 - 0
cache/replace_edb_info.go

@@ -0,0 +1,22 @@
+package cache
+
+import (
+	"eta/eta_api/models/data_manage"
+	"eta/eta_api/utils"
+	"fmt"
+)
+
+// 将替换指标操作加入到队列中
+func AddReplaceEdbInfo(oldEdbInfo, newEdbInfo *data_manage.EdbInfo) bool {
+	record := new(data_manage.ReplaceEdbInfoItem)
+	record.OldEdbInfo = oldEdbInfo
+	record.NewEdbInfo = newEdbInfo
+	if utils.Re == nil {
+		err := utils.Rc.LPush(utils.CACHE_KEY_REPLACE_EDB, record)
+		if err != nil {
+			fmt.Println("AddReplaceEdbInfo LPush Err:" + err.Error())
+		}
+		return true
+	}
+	return false
+}

+ 10 - 10
controllers/classify.go

@@ -203,14 +203,14 @@ func (this *ClassifyController) Add() {
 	}*/
 	//获取报告分类权限列表
 	if classify.ParentId > 0 { //二级分类才能修改权限
-		err = models.EditChartPermissionSearchKeyWordMappingMulti(req.ClassifyName, req.ChartPermissionIdList)
+		err = models.EditChartPermissionSearchKeyWordMappingMulti(req.ClassifyName, req.ChartPermissionIdList, classify.Id)
 		if err != nil {
 			br.Msg = "修改分类权限失败"
 			br.ErrMsg = "修改分类权限失败,Err:" + err.Error()
 			return
 		}
 		go func() {
-			_ = services.EditClassifyChartPermissionSync(req.ClassifyName)
+			_ = services.EditClassifyChartPermissionSync(req.ClassifyName, classify.Id)
 		}()
 	}
 
@@ -528,14 +528,14 @@ func (this *ClassifyController) Edit() {
 	// 为二级分类时, 更新父级分类是否含电话会字段
 	if req.ParentId > 0 {
 		//二级分类才能修改权限
-		err = models.EditChartPermissionSearchKeyWordMappingMulti(item.ClassifyName, req.ChartPermissionIdList)
+		err = models.EditChartPermissionSearchKeyWordMappingMulti(item.ClassifyName, req.ChartPermissionIdList, req.ClassifyId)
 		if err != nil {
 			br.Msg = "修改分类权限失败"
 			br.ErrMsg = "修改分类权限失败,Err:" + err.Error()
 			return
 		}
 		go func() {
-			_ = services.EditClassifyChartPermissionSync(item.ClassifyName)
+			_ = services.EditClassifyChartPermissionSync(item.ClassifyName, req.ClassifyId)
 		}()
 		/*go func() {
 			_ = services.UpdateParentClassifyHasTel(req.ClassifyId, req.ParentId, req.HasTeleconference)
@@ -817,10 +817,10 @@ func (this *ClassifyController) ListClassify() {
 
 	// 查询分类绑定的权限
 	permissionList, _ := models.GetAllPermissionMapping()
-	classifyPermissionMap := make(map[string][]int, 0)
+	classifyPermissionMap := make(map[int][]int, 0)
 	if len(permissionList) > 0 {
 		for _, v := range permissionList {
-			classifyPermissionMap[v.KeyWord] = append(classifyPermissionMap[v.KeyWord], v.ChartPermissionId)
+			classifyPermissionMap[v.ClassifyId] = append(classifyPermissionMap[v.ClassifyId], v.ChartPermissionId)
 		}
 	}
 	// 二级分类
@@ -834,7 +834,7 @@ func (this *ClassifyController) ListClassify() {
 			Classify:       *children[i],
 			ClassifyMenuId: relateMap[children[i].Id],
 		}
-		if permissionIds, ok := classifyPermissionMap[children[i].ClassifyName]; ok {
+		if permissionIds, ok := classifyPermissionMap[children[i].Id]; ok {
 			tmp.ChartPermissionIdList = permissionIds
 		}
 		childrenMap[children[i].ParentId] = append(childrenMap[children[i].ParentId], tmp)
@@ -882,7 +882,7 @@ func (this *ClassifyController) ClassifyPermission() {
 	}
 
 	//获取报告分类权限列表
-	list, err := models.GetPermission(classifyInfo.ClassifyName)
+	list, err := models.GetPermission(classifyInfo.Id)
 	if err != nil {
 		br.Msg = "获取分类信息失败"
 		br.ErrMsg = "获取失败,Err:" + err.Error()
@@ -933,14 +933,14 @@ func (this *ClassifyController) EditClassifyPermission() {
 	}
 
 	//获取报告分类权限列表
-	err = models.EditChartPermissionSearchKeyWordMappingMulti(classifyInfo.ClassifyName, req.ChartPermissionIdList)
+	err = models.EditChartPermissionSearchKeyWordMappingMulti(classifyInfo.ClassifyName, req.ChartPermissionIdList, req.ClassifyId)
 	if err != nil {
 		br.Msg = "修改分类权限失败"
 		br.ErrMsg = "修改分类权限失败,Err:" + err.Error()
 		return
 	}
 	go func() {
-		_ = services.EditClassifyChartPermissionSync(classifyInfo.ClassifyName)
+		_ = services.EditClassifyChartPermissionSync(classifyInfo.ClassifyName, req.ClassifyId)
 	}()
 	// 是关联电话会二级分类修改了权限, 同步关联报告电话会的分类
 	//if classifyInfo.ParentId > 0 && classifyInfo.RelateTel == 1 {

+ 599 - 0
controllers/data_manage/ccf_data.go

@@ -0,0 +1,599 @@
+package data_manage
+
+import (
+	"eta/eta_api/models"
+	"eta/eta_api/models/data_manage"
+	"eta/eta_api/utils"
+	"fmt"
+	"github.com/rdlucklib/rdluck_tools/paging"
+	"github.com/tealeg/xlsx"
+	"os"
+	"path/filepath"
+	"strings"
+	"time"
+)
+
+// CCFClassify
+// @Title CCF化纤分类
+// @Description CCF化纤分类接口
+// @Success 200 {object} data_manage.BaseFromCCFClassifyItem
+// @router /ccf/classify [get]
+func (this *EdbInfoController) CCFClassify() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+
+	classifies, e := data_manage.GetBaseFromCCFClassify()
+	if e != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取CCF化纤分类失败, Err: " + e.Error()
+		return
+	}
+
+	classifyOb := new(data_manage.BaseFromCCFClassify)
+	resp := make([]*data_manage.BaseFromCCFClassifyItem, 0)
+	parentMap := make(map[int][]*data_manage.BaseFromCCFClassifyItem)
+	for _, v := range classifies {
+		t := classifyOb.Format2Item(v)
+		if v.ParentId == 0 {
+			resp = append(resp, t)
+		}
+		if v.ParentId > 0 {
+			if parentMap[v.ParentId] == nil {
+				parentMap[v.ParentId] = make([]*data_manage.BaseFromCCFClassifyItem, 0)
+			}
+			parentMap[v.ParentId] = append(parentMap[v.ParentId], t)
+		}
+	}
+	for _, v := range resp {
+		v.Child = parentMap[v.ClassifyId]
+	}
+
+	br.Data = resp
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+}
+
+// CCFIndexData
+// @Title 获取CCF化纤数据
+// @Description 获取CCF化纤接口
+// @Param   PageSize   query   int  true       "每页数据条数"
+// @Param   CurrentIndex   query   int  true       "当前页页码,从1开始"
+// @Param   ClassifyId   query   string  true       "分类id"
+// @Success 200 {object} data_manage.LzFrequency
+// @router /ccf/index/data [get]
+func (this *EdbInfoController) CCFIndexData() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+
+	pageSize, _ := this.GetInt("PageSize")
+	currentIndex, _ := this.GetInt("CurrentIndex")
+	var startSize int
+
+	if pageSize <= 0 {
+		pageSize = utils.PageSize20
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	startSize = utils.StartIndex(currentIndex, pageSize)
+
+	classifyId, _ := this.GetInt("ClassifyId")
+	if classifyId < 0 {
+		br.Msg = "请选择分类"
+		br.ErrMsg = "请选择分类"
+		return
+	}
+
+	// 获取指标
+	var condition string
+	var pars []interface{}
+	if classifyId >= 0 {
+		condition += ` AND classify_id=? `
+		pars = append(pars, classifyId)
+	}
+
+	indexes, err := data_manage.GetCCFIndex(condition, pars)
+	if err != nil {
+		br.Msg = "获取数据失败"
+		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+		return
+	}
+
+	indexCodes := make([]string, 0)
+	for _, v := range indexes {
+		indexCodes = append(indexCodes, v.IndexCode)
+	}
+	indexCounts, e := data_manage.GetCCFIndexDataCountGroup(indexCodes)
+	if e != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取指标数据总量失败, Err:" + err.Error()
+		return
+	}
+	countMap := make(map[string]int)
+	for _, v := range indexCounts {
+		countMap[v.IndexCode] = v.Count
+	}
+
+	resultList := make([]*data_manage.BaseFromCCFIndexList, 0)
+	for _, v := range indexes {
+		product := new(data_manage.BaseFromCCFIndexList)
+		product.BaseFromCcfIndexId = v.BaseFromCcfIndexId
+		product.ClassifyId = v.ClassifyId
+		product.Unit = v.Unit
+		product.IndexCode = v.IndexCode
+		product.IndexName = v.IndexName
+		product.Frequency = v.Frequency
+		product.CreateTime = v.CreateTime
+		product.ModifyTime = v.ModifyTime
+
+		total := countMap[v.IndexCode]
+		page := paging.GetPaging(currentIndex, pageSize, total)
+		dataList, e := data_manage.GetCCFIndexData(v.IndexCode, startSize, pageSize)
+		if e != nil {
+			br.Msg = "获取数据失败"
+			br.ErrMsg = "获取指标数据失败,Err:" + e.Error()
+			return
+		}
+		if dataList == nil {
+			dataList = make([]*data_manage.BaseFromCCFData, 0)
+		}
+		product.DataList = dataList
+		product.Paging = page
+		resultList = append(resultList, product)
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resultList
+}
+
+// CCFSearchList
+// @Title CCF模糊搜索
+// @Description CCF模糊搜索
+// @Param   Keyword   query   string  ture       "关键字搜索"
+// @Success 200 {object} data_manage.BaseFromCCFIndexSearchItem
+// @router /ccf/search_list [get]
+func (this *EdbInfoController) CCFSearchList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+
+	list := make([]*data_manage.BaseFromCCFIndexSearchItem, 0)
+	var err error
+	// 关键字
+	keyword := this.GetString("Keyword")
+	if keyword != "" {
+		keyWordArr := strings.Split(keyword, " ")
+
+		if len(keyWordArr) > 0 {
+			condition := ""
+			for _, v := range keyWordArr {
+				condition += ` AND CONCAT(index_name,index_code) LIKE '%` + v + `%'`
+			}
+			list, err = data_manage.GetCCFItemList(condition)
+			if err != nil {
+				br.ErrMsg = "获取失败,Err:" + err.Error()
+				br.Msg = "获取失败"
+				return
+			}
+		}
+	} else {
+		list, err = data_manage.GetCCFItemList("")
+		if err != nil {
+			br.ErrMsg = "获取失败,Err:" + err.Error()
+			br.Msg = "获取失败"
+			return
+		}
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = list
+}
+
+// CCFSingleData
+// @Title 获取CCF数据
+// @Description 获取CCF单条数据接口
+// @Param   IndexCode   query   string  true       "指标唯一编码"
+// @Success 200 {object} models.BaseResponse
+// @router /ccf/single_data [get]
+func (this *EdbInfoController) CCFSingleData() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	indexCode := this.GetString("IndexCode")
+	indexInfo, err := data_manage.GetBaseFromCCFIndexByIndexCode(indexCode)
+	if err != nil {
+		br.Msg = "获取指标信息失败"
+		br.ErrMsg = "获取指标信息失败,Err:" + err.Error()
+		return
+	}
+	dataTmpList, err := data_manage.GetCCFIndexDataByCode(indexCode)
+	if err != nil {
+		br.Msg = "获取数据失败"
+		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+		return
+	}
+	var ret data_manage.CCFSingleDataResp
+	var dataList []*data_manage.CCFSingleData
+
+	ret.ClassifyId = indexInfo.ClassifyId
+	ret.BaseFromCcfIndexId = indexInfo.BaseFromCcfIndexId
+	ret.IndexCode = indexInfo.IndexCode
+	ret.IndexName = indexInfo.IndexName
+	ret.Frequency = indexInfo.Frequency
+	ret.CreateTime = indexInfo.CreateTime.Format(utils.FormatDateTime)
+	ret.ModifyTime = indexInfo.ModifyTime.Format(utils.FormatDateTime)
+	ret.Unit = indexInfo.Unit
+	for _, v := range dataTmpList {
+		tmp := &data_manage.CCFSingleData{
+			Value:    v.Value,
+			DataTime: v.DataTime,
+		}
+		dataList = append(dataList, tmp)
+	}
+	ret.Data = dataList
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = ret
+}
+
+// ExportCCFList
+// @Title 导出CCF数据
+// @Description 导出CCF数据
+// @Param   IndexName   query   string  false       "名称关键词"
+// @Param   IndexCode   query   string  false       "指标唯一编码"
+// @Param   ClassifyId   query   string  true       "分类"
+// @Success 200  导出成功
+// @router /ccf/export [get]
+func (this *EdbInfoController) ExportCCFList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请重新登录"
+		return
+	}
+
+	indexCode := this.GetString("IndexCode") //指标唯一编码
+	classifyId, _ := this.GetInt("ClassifyId")
+
+	dir, _ := os.Executable()
+	exPath := filepath.Dir(dir)
+
+	downFile := exPath + "/" + time.Now().Format(utils.FormatDateTimeUnSpace) + ".xlsx"
+	xlsxFile := xlsx.NewFile()
+
+	var pars []interface{}
+	condition := ""
+	if classifyId > 0 {
+		//获取指标
+		condition += " AND classify_id=?"
+		pars = append(pars, classifyId)
+	}
+	if indexCode != "" {
+		//获取指标
+		condition += " AND index_code=?"
+		pars = append(pars, indexCode)
+	}
+	indexList, err := data_manage.GetCCFIndex(condition, pars)
+	if err != nil {
+		fmt.Println("获取数据失败,Err:" + err.Error())
+		return
+	}
+	if len(indexList) <= 0 {
+		fmt.Println("indexList 为空")
+		br.Ret = 200
+		br.Success = true
+		br.Msg = "success"
+		return
+	}
+	sheetNew := new(xlsx.Sheet)
+	sheetNew, err = xlsxFile.AddSheet("CCF化纤")
+
+	//sheetNew.SetColWidth()
+	//获取指标数据
+	windRow := sheetNew.AddRow()
+	secNameRow := sheetNew.AddRow()
+	indexCodeRow := sheetNew.AddRow()
+	frequencyRow := sheetNew.AddRow()
+	unitRow := sheetNew.AddRow()
+	lastModifyDateRow := sheetNew.AddRow()
+	//获取分类下指标最大数据量
+	var dataMax int
+	setRowIndex := 6
+	indexCodeList := make([]string, 0)
+	for _, v := range indexList {
+		indexCodeList = append(indexCodeList, v.IndexCode)
+	}
+	dataListMap := make(map[string][]*data_manage.BaseFromCCFData)
+	if len(indexList) > 0 {
+		allDataList, e := data_manage.GetCCFIndexDataByCodes(indexCodeList)
+		if e != nil {
+			br.Msg = "获取数据失败"
+			br.ErrMsg = "获取数据失败,Err:" + e.Error()
+			return
+		}
+		for _, v := range allDataList {
+			dataListMap[v.IndexCode] = append(dataListMap[v.IndexCode], v)
+		}
+		for _, v := range dataListMap {
+			if len(v) > dataMax {
+				dataMax = len(v)
+			}
+		}
+	}
+
+	for k, sv := range indexList {
+		//获取数据
+		dataList, ok := dataListMap[sv.IndexCode]
+		if !ok {
+			continue
+		}
+		if len(dataList) > 0 {
+			windRow.AddCell().SetValue("CCF化纤")
+			secNameRow.AddCell().SetValue("指标名称")
+			indexCodeRow.AddCell().SetValue("指标ID")
+			frequencyRow.AddCell().SetValue("频率")
+			unitRow.AddCell().SetValue("单位")
+			lastModifyDateRow.AddCell().SetValue("更新时间")
+
+			secNameRow.AddCell().SetValue(sv.IndexName)
+			indexCodeRow.AddCell().SetValue(sv.IndexCode)
+			frequencyRow.AddCell().SetValue(sv.Frequency)
+
+			unitRow.AddCell().SetValue(sv.Unit)
+			lastModifyDateRow.AddCell().SetValue(sv.ModifyTime)
+
+			windRow.AddCell()
+			windRow.AddCell()
+			secNameRow.AddCell()
+			indexCodeRow.AddCell()
+			frequencyRow.AddCell()
+			unitRow.AddCell()
+			lastModifyDateRow.AddCell()
+			minCol := k * 3
+			sheetNew.SetColWidth(minCol, minCol, 15)
+
+			if len(dataList) <= 0 {
+				for n := 0; n < dataMax; n++ {
+					rowIndex := setRowIndex + n
+					row := sheetNew.Row(rowIndex)
+					row.AddCell()
+					row.AddCell()
+					row.AddCell()
+				}
+			} else {
+				endRowIndex := 0
+				for rk, dv := range dataList {
+					rowIndex := setRowIndex + rk
+					row := sheetNew.Row(rowIndex)
+					displayDate, _ := time.Parse(utils.FormatDate, dv.DataTime)
+					displayDateCell := row.AddCell()
+					style := new(xlsx.Style)
+					style.ApplyAlignment = true
+					style.Alignment.WrapText = true
+					displayDateCell.SetStyle(style)
+					displayDateCell.SetDate(displayDate)
+
+					row.AddCell().SetValue(dv.Value)
+					row.AddCell()
+					endRowIndex = rowIndex
+				}
+				if len(dataList) < dataMax {
+					dataLen := dataMax - len(dataList)
+					for n := 0; n < dataLen; n++ {
+						rowIndex := (endRowIndex + 1) + n
+						row := sheetNew.Row(rowIndex)
+						row.AddCell()
+						row.AddCell()
+						row.AddCell()
+					}
+				}
+			}
+		}
+	}
+
+	err = xlsxFile.Save(downFile)
+	if err != nil {
+		//有指标无数据时先导出一遍空表
+		sheet, err := xlsxFile.AddSheet("无数据")
+		if err != nil {
+			br.Msg = "新增Sheet失败"
+			br.ErrMsg = "新增Sheet失败,Err:" + err.Error()
+			return
+		}
+		rowSecName := sheet.AddRow()
+		celSecName := rowSecName.AddCell()
+		celSecName.SetValue("")
+		err = xlsxFile.Save(downFile)
+		if err != nil {
+			br.Msg = "保存文件失败"
+			br.ErrMsg = "保存文件失败"
+			return
+		}
+	}
+	fileName := `CCF化纤信息`
+	//if len(indexList) > 0 {
+	//	fileName = indexList[0].IndexName
+	//}
+	fileName += time.Now().Format("06.01.02") + `.xlsx` //文件名称
+	this.Ctx.Output.Download(downFile, fileName)
+	defer func() {
+		os.Remove(downFile)
+	}()
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "success"
+
+}
+
+// CCFStockClassify
+// @Title CCF化纤信息-装置分类
+// @Description CCF化纤信息-装置分类
+// @Success 200 {object} data_manage.CCFStockClassify
+// @router /ccf/stock/classify [get]
+func (this *EdbInfoController) CCFStockClassify() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+
+	classifyOb := new(data_manage.CCFStockClassify)
+	items, e := classifyOb.GetItemsByCondition(``, make([]interface{}, 0), []string{}, "ccf_stock_classify_id ASC")
+	if e != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取CCF化纤分类列表失败, Err: " + e.Error()
+		return
+	}
+	resp := make([]*data_manage.CCFStockClassifyItem, 0)
+	for _, v := range items {
+		resp = append(resp, v.Format2Item())
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+// CCFStockTable
+// @Title CCF化纤信息-装置表格详情
+// @Description CCF化纤信息-装置表格详情
+// @Param   ClassifyId   query   int  true       "分类ID"
+// @Param   TableDate   query   string  false       "表格日期"
+// @Success 200 {object} data_manage.CCFStockExcel
+// @router /ccf/stock/table [get]
+func (this *EdbInfoController) CCFStockTable() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+
+	classifyId, _ := this.GetInt("ClassifyId", 0)
+	tableDate := this.GetString("TableDate")
+	if tableDate != "" {
+		_, e := time.ParseInLocation(utils.FormatDate, tableDate, time.Local)
+		if e != nil {
+			br.Msg = "日期格式有误"
+			return
+		}
+	}
+
+	excelOb := new(data_manage.CCFStockExcel)
+	cond := ``
+	pars := make([]interface{}, 0)
+	if classifyId > 0 {
+		cond += fmt.Sprintf(` AND %s = ?`, excelOb.Cols().ClassifyId)
+		pars = append(pars, classifyId)
+	}
+	if tableDate != "" {
+		cond += fmt.Sprintf(` AND %s = ?`, excelOb.Cols().ExcelDate)
+		pars = append(pars, tableDate)
+	}
+
+	// 若无tableDate默认取最近的有数据的表格
+	item, e := excelOb.GetItemByCondition(cond, pars, fmt.Sprintf("%s DESC", excelOb.Cols().ExcelDate))
+	if e != nil {
+		if e.Error() == utils.ErrNoRow() {
+			br.Ret = 200
+			br.Success = true
+			br.Msg = "该日期暂无数据"
+			br.Data = data_manage.CCFStockExcel{}
+			return
+		}
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取CCF化纤装置表格失败, Err: " + e.Error()
+		return
+	}
+	resp := item.Format2Item()
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}

+ 18 - 2
controllers/data_manage/chart_info.go

@@ -2940,6 +2940,14 @@ func (this *EdbInfoController) BatchChartInfoRefresh() {
 		br.ErrMsg = "参数解析失败,Err:" + err.Error()
 		return
 	}
+	if req.Source == "" {
+		br.Msg = "刷新来源有误"
+		return
+	}
+	if req.PrimaryId <= 0 {
+		br.Msg = "刷新对象有误"
+		return
+	}
 
 	//获取所有的图表列表
 	_, chartInfoList, err := data_manage.GetChartInfoListByUniqueCodeSlice(req.ChartInfoCode)
@@ -2950,7 +2958,7 @@ func (this *EdbInfoController) BatchChartInfoRefresh() {
 		return
 	}
 
-	redisKey := data.GetBatchChartRefreshKey(req.Source, req.ReportId, req.ReportChapterId)
+	redisKey := data.GetBatchChartRefreshKey(req.Source, req.PrimaryId, req.SubId)
 
 	// 图表中的指标刷新
 	err, isAsync := data.BatchChartInfoRefreshV2(chartInfoList, redisKey)
@@ -3462,9 +3470,17 @@ func (this *EdbInfoController) GetBatchChartRefreshResult() {
 		br.ErrMsg = "参数解析失败,Err:" + err.Error()
 		return
 	}
+	if req.Source == "" {
+		br.Msg = "刷新来源有误"
+		return
+	}
+	if req.PrimaryId <= 0 {
+		br.Msg = "刷新对象有误"
+		return
+	}
 
 	// 刷新结果,默认是刷新完成了
-	refreshResult := data.CheckBatchChartRefreshResult(req.Source, req.ReportId, req.ReportChapterId)
+	refreshResult := data.CheckBatchChartRefreshResult(req.Source, req.PrimaryId, req.SubId)
 
 	resp := response.ChartRefreshResp{
 		RefreshResult: refreshResult,

+ 9 - 2
controllers/data_manage/edb_classify.go

@@ -356,7 +356,7 @@ func (this *EdbClassifyController) DeleteEdbClassifyCheck() {
 		br.IsSendEmail = false
 		return
 	}
-	deleteStatus, tipsMsg, err, errMsg := data.DeleteCheck(req.ClassifyId, req.EdbInfoId, this.SysUser)
+	deleteStatus, tipsMsg, tableList, err, errMsg := data.DeleteCheck(req.ClassifyId, req.EdbInfoId, this.SysUser)
 	if errMsg != `` {
 		br.Msg = errMsg
 		br.ErrMsg = errMsg
@@ -367,6 +367,12 @@ func (this *EdbClassifyController) DeleteEdbClassifyCheck() {
 		}
 		return
 	}
+	if this.Lang == "en" {
+		if utils.ViperConfig.InConfig(tipsMsg) {
+			tipsMsg = utils.ViperConfig.GetString(tipsMsg)
+		}
+	}
+
 	//var deleteStatus int
 	//var tipsMsg string
 	////删除分类
@@ -429,6 +435,7 @@ func (this *EdbClassifyController) DeleteEdbClassifyCheck() {
 	resp := new(data_manage.ClassifyDeleteCheckResp)
 	resp.DeleteStatus = deleteStatus
 	resp.TipsMsg = tipsMsg
+	resp.TableList = tableList
 	br.Ret = 200
 	br.Msg = "检测成功"
 	br.Success = true
@@ -467,7 +474,7 @@ func (this *EdbClassifyController) DeleteEdbClassify() {
 		return
 	}
 
-	nextItem, err, errMsg := data.Delete(req.ClassifyId, req.EdbInfoId, sysUser, string(this.Ctx.Input.RequestBody), this.Ctx.Input.URI())
+	nextItem, _, err, errMsg := data.Delete(req.ClassifyId, req.EdbInfoId, sysUser, string(this.Ctx.Input.RequestBody), this.Ctx.Input.URI())
 	if errMsg != `` {
 		br.Msg = errMsg
 		br.ErrMsg = errMsg

+ 71 - 40
controllers/data_manage/edb_info.go

@@ -2,10 +2,12 @@ package data_manage
 
 import (
 	"encoding/json"
+	"eta/eta_api/cache"
 	"eta/eta_api/controllers"
 	"eta/eta_api/models"
 	"eta/eta_api/models/company"
 	"eta/eta_api/models/data_manage"
+	"eta/eta_api/models/data_manage/cross_variety"
 	request2 "eta/eta_api/models/data_manage/excel/request"
 	"eta/eta_api/models/data_manage/request"
 	"eta/eta_api/models/data_manage/response"
@@ -3885,41 +3887,17 @@ func (this *ChartInfoController) EdbInfoReplace() {
 	//replaceChartTotal, replaceCalculateTotal, err := data.EdbInfoReplace(oldEdbInfo, newEdbInfo, sysAdminId, sysUser.RealName)
 	_, _, err = data.EdbInfoReplace(oldEdbInfo, newEdbInfo, sysAdminId, sysUser.RealName)
 	//msgContent := ``
-	isFail := false
-	var errmsg string
 	if err != nil {
-		//msgContent = oldEdbInfo.EdbName + "指标替换" + newEdbInfo.EdbName + "指标,全部替换失败,涉及" + strconv.Itoa(replaceChartTotal) + "张图表,\n\n " + strconv.Itoa(replaceCalculateTotal) + "个计算指标"
-		isFail = true
-		errmsg = "replace err:" + err.Error()
-	} else {
-		//msgContent = oldEdbInfo.EdbName + "指标替换" + newEdbInfo.EdbName + "指标,全部替换成功,涉及" + strconv.Itoa(replaceChartTotal) + "张图表,\n\n" + strconv.Itoa(replaceCalculateTotal) + "个计算指标"
-		isFail = false
-	}
-
-	// 添加站内信息
-	//{
-	//	msgItem := new(company.CompanyApprovalMessage)
-	//	msgItem.CreateUserId = sysAdminId
-	//	msgItem.ReceiveUserId = sysAdminId
-	//	msgItem.MessageStatus = 0
-	//	msgItem.Remark = "指标替换"
-	//	msgItem.OperationStatus = 1
-	//	msgItem.Content = msgContent
-	//	msgItem.CreateTime = time.Now()
-	//	msgItem.ModifyTime = time.Now()
-	//	msgItem.MessageType = 3 //1:申请消息,2:审批结果,3:文字消息
-	//	msgItem.SourceType = 4  //消息来源
-	//	err = company.AddCompanyApprovalMessage(msgItem)
-	//}
-
-	if isFail {
 		br.Msg = "替换失败"
-		br.ErrMsg = "替换失败 err:" + errmsg
-	} else {
-		br.Msg = "替换成功"
-		br.ErrMsg = "替换成功"
-		br.Ret = 200
+		br.ErrMsg = "替换失败 replace err:" + err.Error()
+		return
 	}
+
+	//加入到缓存队列中处理
+	go cache.AddReplaceEdbInfo(oldEdbInfo, newEdbInfo)
+	br.Msg = "替换成功"
+	br.ErrMsg = "替换成功"
+	br.Ret = 200
 	br.IsAddLog = true
 	return
 }
@@ -3974,9 +3952,9 @@ func (this *EdbInfoController) RelationChartList() {
 		return
 	}
 
-	// 关联指标
+	/*// 关联指标
 	condition += ` AND b.edb_info_id = ? `
-	pars = append(pars, edbInfoId)
+	pars = append(pars, edbInfoId)*/
 
 	//只看我的
 	isShowMe, _ := this.GetBool("IsShowMe")
@@ -3985,8 +3963,47 @@ func (this *EdbInfoController) RelationChartList() {
 		pars = append(pars, sysUser.AdminId)
 	}
 
+	chartIds := make([]int, 0)
+	chartIdMap := make(map[int]bool)
+	// 查询指标绑定的图表
+	edbListTemp, err := data_manage.GetEdbMappingListByEdbInfoId(edbInfoId)
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		br.Msg = "获取图表信息失败"
+		br.ErrMsg = "获取图表信息失败,Err:" + err.Error()
+		return
+	}
+	for _, v := range edbListTemp {
+		if _, ok := chartIdMap[v.ChartInfoId]; !ok {
+			chartIdMap[v.ChartInfoId] = true
+		}
+	}
+	// 查询跨品种的图表
+	tagXList, err := cross_variety.GetChartInfoCrossVarietyByXEdbInfoId(edbInfoId)
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		br.Msg = "获取图表信息失败"
+		br.ErrMsg = "获取图表信息失败,Err:" + err.Error()
+		return
+	}
+
+	for _, v := range tagXList {
+		if _, ok := chartIdMap[v.ChartInfoId]; !ok {
+			chartIdMap[v.ChartInfoId] = true
+		}
+	}
+
+	tagYList, err := cross_variety.GetChartInfoCrossVarietyByYEdbInfoId(edbInfoId)
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		br.Msg = "获取图表信息失败"
+		br.ErrMsg = "获取图表信息失败,Err:" + err.Error()
+		return
+	}
+	for _, v := range tagYList {
+		if _, ok := chartIdMap[v.ChartInfoId]; !ok {
+			chartIdMap[v.ChartInfoId] = true
+		}
+	}
+
 	// 获取当前账号的不可见图表
-	noPermissionChartIdList := make([]int, 0)
 	{
 		obj := data_manage.EdbInfoNoPermissionAdmin{}
 		confList, err := obj.GetAllChartListByAdminId(this.SysUser.AdminId)
@@ -3996,15 +4013,29 @@ func (this *EdbInfoController) RelationChartList() {
 			return
 		}
 		for _, v := range confList {
-			noPermissionChartIdList = append(noPermissionChartIdList, v.ChartInfoId)
+			if _, ok := chartIdMap[v.ChartInfoId]; ok {
+				delete(chartIdMap, v.ChartInfoId)
+			}
 		}
 	}
-	noPermissionChartIdNum := len(noPermissionChartIdList)
-	if noPermissionChartIdNum > 0 {
-		condition += ` AND a.chart_info_id not in  (` + utils.GetOrmInReplace(noPermissionChartIdNum) + `) `
-		pars = append(pars, noPermissionChartIdList)
+	for k, _ := range chartIdMap {
+		chartIds = append(chartIds, k)
 	}
 
+	// 关联指标
+	if len(chartIds) > 0 {
+		condition += `  AND a.chart_info_id in  (` + utils.GetOrmInReplace(len(chartIds)) + `)`
+		pars = append(pars, chartIds)
+	} else {
+		items := make([]*data_manage.ChartInfoView, 0)
+		resp.Paging = page
+		resp.List = items
+		br.Ret = 200
+		br.Success = true
+		br.Msg = "获取成功"
+		return
+	}
+	// 得到图表ID
 	//获取关联图表列表
 	list, err := data_manage.GetRelationChartListByCondition(condition, pars, startSize, pageSize)
 	if err != nil && err.Error() != utils.ErrNoRow() {

+ 18 - 2
controllers/data_manage/excel/excel_info.go

@@ -2694,6 +2694,14 @@ func (c *ExcelInfoController) BatchRefresh() {
 		br.Msg = "刷新成功"
 		return
 	}
+	if req.Source == "" {
+		br.Msg = "刷新来源有误"
+		return
+	}
+	if req.PrimaryId <= 0 {
+		br.Msg = "刷新对象有误"
+		return
+	}
 
 	// 获取表格关联的指标IDs
 	edbIds, e := excel2.GetEdbIdsFromExcelCodes(req.ExcelCodes, sysUser.AdminId, c.Lang)
@@ -2703,7 +2711,7 @@ func (c *ExcelInfoController) BatchRefresh() {
 		return
 	}
 
-	redisKey := data.GetBatchChartRefreshKey(req.Source, req.ReportId, req.ReportChapterId)
+	redisKey := data.GetBatchChartRefreshKey(req.Source, req.PrimaryId, req.SubId)
 	refreshKeys := make([]string, 0)
 	for _, v := range req.ExcelCodes {
 		refreshKeys = append(refreshKeys, fmt.Sprint(utils.HZ_CHART_LIB_EXCEL_TABLE_DETAIL, v))
@@ -2751,10 +2759,18 @@ func (c *ExcelInfoController) GetBatchChartRefreshResult() {
 		br.ErrMsg = "参数解析失败,Err:" + err.Error()
 		return
 	}
+	if req.Source == "" {
+		br.Msg = "刷新来源有误"
+		return
+	}
+	if req.PrimaryId <= 0 {
+		br.Msg = "刷新对象有误"
+		return
+	}
 
 	// 校验缓存是否存在, 存在说明还在刷新中
 	result := true
-	redisKey := excel2.GetExcelEdbBatchRefreshKey(req.Source, req.ReportId, req.ReportChapterId)
+	redisKey := excel2.GetExcelEdbBatchRefreshKey(req.Source, req.PrimaryId, req.SubId)
 	if redisKey != `` {
 		// 如果找到了key,那么就是还在更新中
 		ok := utils.Rc.IsExist(redisKey)

+ 3 - 2
controllers/data_manage/predict_edb_classify.go

@@ -302,7 +302,7 @@ func (this *PredictEdbClassifyController) DeleteCheck() {
 		return
 	}
 
-	deleteStatus, tipsMsg, err, errMsg := data.DeleteCheck(req.ClassifyId, req.EdbInfoId, this.SysUser)
+	deleteStatus, tipsMsg, tableList, err, errMsg := data.DeleteCheck(req.ClassifyId, req.EdbInfoId, this.SysUser)
 	if errMsg != `` {
 		br.Msg = errMsg
 		br.ErrMsg = errMsg
@@ -317,6 +317,7 @@ func (this *PredictEdbClassifyController) DeleteCheck() {
 	resp := new(data_manage.ClassifyDeleteCheckResp)
 	resp.DeleteStatus = deleteStatus
 	resp.TipsMsg = tipsMsg
+	resp.TableList = tableList
 	br.Ret = 200
 	br.Msg = "检测成功"
 	br.Success = true
@@ -356,7 +357,7 @@ func (this *PredictEdbClassifyController) Delete() {
 		return
 	}
 
-	nextItem, err, errMsg := data.Delete(req.ClassifyId, req.EdbInfoId, sysUser, string(this.Ctx.Input.RequestBody), this.Ctx.Input.URI())
+	nextItem, _, err, errMsg := data.Delete(req.ClassifyId, req.EdbInfoId, sysUser, string(this.Ctx.Input.RequestBody), this.Ctx.Input.URI())
 	if errMsg != `` {
 		br.Msg = errMsg
 		br.ErrMsg = errMsg

+ 15 - 3
controllers/ppt_english.go

@@ -316,7 +316,13 @@ func (this *PptEnglishController) EditPpt() {
 		br.ErrMsg = "PPT目录信息异常"
 		return
 	}
-	if !pptMap.IsMoved && len(pptMapList) > 1 {
+	count, err := ppt_english.GetPptMappingCountByGroupPptId(pptMap.GroupPptId, this.SysUser.AdminId)
+	if err != nil {
+		br.Msg = "获取英文PPT和用户权限关系失败"
+		br.ErrMsg = "获取英文PPT和用户权限关系失败, Err:" + err.Error()
+		return
+	}
+	if !pptMap.IsMoved && len(pptMapList) > 1 && count > 0 {
 		// 如果没有人为移动位置, 默认将当前ppt置顶
 		err = ppt.MoveGroupPptEnglish(pptMap.GroupId, pptMap.GroupPptId, pptMapList[0].GroupPptId, 0, this.SysUser.AdminId)
 		if err != nil {
@@ -774,8 +780,14 @@ func (this *PptEnglishController) SaveLog() {
 		br.ErrMsg = "PPT目录信息异常"
 		return
 	}
-	if !pptMap.IsMoved && len(pptMapList) > 1 {
-		// 如果没有人为移动位置, 默认将当前ppt置顶
+	count, err := ppt_english.GetPptMappingCountByGroupPptId(pptMap.GroupPptId, this.SysUser.AdminId)
+	if err != nil {
+		br.Msg = "获取英文PPT和用户权限关系失败"
+		br.ErrMsg = "获取英文PPT和用户权限关系失败, Err:" + err.Error()
+		return
+	}
+	if !pptMap.IsMoved && len(pptMapList) > 1 && count > 0 {
+		// 如果没有人为移动位置, 且当前用户有权限, 默认将当前ppt置顶
 		err = ppt.MoveGroupPptEnglish(pptMap.GroupId, pptMap.GroupPptId, pptMapList[0].GroupPptId, 0, this.SysUser.AdminId)
 		if err != nil {
 			br.Msg = err.Error()

+ 15 - 3
controllers/ppt_v2.go

@@ -319,7 +319,13 @@ func (this *PptV2Controller) EditPpt() {
 		br.ErrMsg = "PPT目录信息异常"
 		return
 	}
-	if !pptMap.IsMoved && len(pptMapList) > 1 {
+	count, err := models.GetPptMappingByGroupPptCountId(pptMap.GroupPptId, this.SysUser.AdminId)
+	if err != nil {
+		br.Msg = "查询映射关系失败"
+		br.ErrMsg = "查询映射关系失败, 保存失败, Err:" + err.Error()
+		return
+	}
+	if !pptMap.IsMoved && len(pptMapList) > 1 && count > 0 {
 		// 如果没有人为移动位置, 默认将当前ppt置顶
 		err = ppt.MoveGroupPpt(pptMap.GroupId, pptMap.GroupPptId, pptMapList[0].GroupPptId, 0, this.SysUser.AdminId)
 		if err != nil {
@@ -747,8 +753,14 @@ func (this *PptV2Controller) SaveLog() {
 		br.ErrMsg = "PPT目录信息异常"
 		return
 	}
-	if !pptMap.IsMoved && len(pptMapList) > 1 {
-		// 如果没有人为移动位置, 默认将当前ppt置顶
+	count, err := models.GetPptMappingByGroupPptCountId(pptMap.GroupPptId, this.SysUser.AdminId)
+	if err != nil {
+		br.Msg = "查询映射关系失败"
+		br.ErrMsg = "查询映射关系失败, 保存失败, Err:" + err.Error()
+		return
+	}
+	if !pptMap.IsMoved && len(pptMapList) > 1 && count > 0 {
+		// 如果没有人为移动位置, 且当前用户有权限, 默认将当前ppt置顶
 		err = ppt.MoveGroupPpt(pptMap.GroupId, pptMap.GroupPptId, pptMapList[0].GroupPptId, 0, this.SysUser.AdminId)
 		if err != nil {
 			br.Msg = err.Error()

+ 4 - 4
controllers/report.go

@@ -600,7 +600,7 @@ func (this *ReportController) Add() {
 	//处理权限
 	//if utils.BusinessCode == utils.BusinessCodeRelease || utils.BusinessCode == utils.BusinessCodeSandbox {
 	go func() {
-		permissionItems, e := models.GetPermission(req.ClassifyNameSecond)
+		permissionItems, e := models.GetPermission(req.ClassifyIdSecond)
 		if e != nil {
 			alarm_msg.SendAlarmMsg("获取权限失败,Err:"+e.Error(), 3)
 			return
@@ -613,7 +613,7 @@ func (this *ReportController) Add() {
 			}
 		}
 		// 同步crm权限
-		_ = services.EditReportPermissionSync(newReportId, req.ClassifyNameSecond)
+		_ = services.EditReportPermissionSync(newReportId, req.ClassifyIdSecond)
 	}()
 	//}
 
@@ -770,7 +770,7 @@ func (this *ReportController) Edit() {
 			alarm_msg.SendAlarmMsg("修改删除报告权限失败,Err:"+e.Error(), 3)
 			return
 		}
-		permissionItems, e := models.GetPermission(req.ClassifyNameSecond)
+		permissionItems, e := models.GetPermission(req.ClassifyIdSecond)
 		if e != nil {
 			alarm_msg.SendAlarmMsg("获取权限失败,Err:"+e.Error(), 3)
 			return
@@ -783,7 +783,7 @@ func (this *ReportController) Edit() {
 			}
 		}
 		// 同步crm权限
-		_ = services.EditReportPermissionSync(req.ReportId, req.ClassifyNameSecond)
+		_ = services.EditReportPermissionSync(req.ReportId, req.ClassifyIdSecond)
 	}()
 	//}
 

+ 26 - 4
controllers/sandbox/sandbox.go

@@ -2383,8 +2383,15 @@ func (this *SandboxController) LinkEdbInfoCheck() {
 		br.ErrMsg = "获取指标信息失败,err:" + err.Error()
 		return
 	}
+	edbList := make([]*sandbox.SandboxLinkCheckItem, 0)
 	for _, v := range edbInfoList {
-		resp.EdbInfoIdList = append(resp.EdbInfoIdList, v.EdbInfoId)
+		tmp := &sandbox.SandboxLinkCheckItem{
+			Id:         v.EdbInfoId,
+			Name:       v.EdbName,
+			UniqueCode: v.UniqueCode,
+			ClassifyId: v.ClassifyId,
+		}
+		edbList = append(edbList, tmp)
 	}
 
 	chartList, err := data_manage.GetChartInfoByIdList(req.ChartInfoIdList)
@@ -2393,8 +2400,15 @@ func (this *SandboxController) LinkEdbInfoCheck() {
 		br.ErrMsg = `获取图表列表失败,ERR:` + err.Error()
 		return
 	}
+	chartListTmp := make([]*sandbox.SandboxLinkCheckItem, 0)
 	for _, v := range chartList {
-		resp.ChartInfoIdList = append(resp.ChartInfoIdList, v.ChartInfoId)
+		tmp := &sandbox.SandboxLinkCheckItem{
+			Id:         v.ChartInfoId,
+			Name:       v.ChartName,
+			UniqueCode: v.UniqueCode,
+			ClassifyId: v.ChartClassifyId,
+		}
+		chartListTmp = append(chartListTmp, tmp)
 	}
 
 	reportList, err := models.GetSimpleReportByIds(req.ReportIdList)
@@ -2403,10 +2417,18 @@ func (this *SandboxController) LinkEdbInfoCheck() {
 		br.ErrMsg = `获取报告列表失败,ERR:` + err.Error()
 		return
 	}
+	reportListTmp := make([]*sandbox.SandboxLinkCheckItem, 0)
 	for _, v := range reportList {
-		resp.ReportIdList = append(resp.ReportIdList, v.Id)
+		tmp := &sandbox.SandboxLinkCheckItem{
+			Id:         v.Id,
+			Name:       v.Title,
+			UniqueCode: v.ReportCode,
+		}
+		reportListTmp = append(reportListTmp, tmp)
 	}
-
+	resp.EdbInfoIdList = edbList
+	resp.ChartInfoIdList = chartListTmp
+	resp.ReportIdList = reportListTmp
 	br.Ret = 200
 	br.Msg = "检测成功"
 	br.Success = true

+ 2 - 2
controllers/smart_report/smart_report.go

@@ -393,7 +393,7 @@ func (this *SmartReportController) Detail() {
 		headResource, err := smart_report.GetResourceItemById(resp.HeadResourceId)
 		if err != nil {
 			br.Msg = "操作失败"
-			br.ErrMsg = "获取资源库版头失败, Err: " + e.Error()
+			br.ErrMsg = "获取资源库版头失败, Err: " + err.Error()
 			return
 		}
 		resp.HeadImg = headResource.ImgUrl
@@ -404,7 +404,7 @@ func (this *SmartReportController) Detail() {
 		endResource, err := smart_report.GetResourceItemById(resp.EndResourceId)
 		if err != nil {
 			br.Msg = "操作失败"
-			br.ErrMsg = "获取资源库版头失败, Err: " + e.Error()
+			br.ErrMsg = "获取资源库版头失败, Err: " + err.Error()
 			return
 		}
 		resp.EndImg = endResource.ImgUrl

+ 144 - 0
models/data_manage/base_from_ccf.go

@@ -0,0 +1,144 @@
+package data_manage
+
+import (
+	"eta/eta_api/utils"
+	"github.com/beego/beego/v2/client/orm"
+	"github.com/rdlucklib/rdluck_tools/paging"
+	"time"
+)
+
+type BaseFromCCFIndex struct {
+	BaseFromCcfIndexId int `orm:"column(base_from_ccf_index_id);pk"`
+	ClassifyId         int
+	IndexCode          string
+	IndexName          string
+	Frequency          string
+	Unit               string
+	Sort               int
+	CreateTime         time.Time
+	ModifyTime         time.Time
+}
+
+type BaseFromCCFIndexList struct {
+	BaseFromCcfIndexId int `orm:"column(base_from_ccf_index_id);pk"`
+	ClassifyId         int
+	IndexCode          string
+	IndexName          string
+	Frequency          string
+	Unit               string
+	Sort               int
+	CreateTime         string
+	ModifyTime         string
+	DataList           []*BaseFromCCFData
+	Paging             *paging.PagingItem `description:"分页数据"`
+}
+
+type CCFSingleDataResp struct {
+	BaseFromCcfIndexId int
+	ClassifyId         int
+	IndexCode          string
+	IndexName          string
+	Frequency          string
+	Unit               string
+	CreateTime         string
+	ModifyTime         string
+	Data               []*CCFSingleData
+}
+
+type CCFSingleData struct {
+	Value    string `orm:"column(value)" description:"日期"`
+	DataTime string `orm:"column(data_time)" description:"值"`
+}
+
+func GetCCFIndex(condition string, pars interface{}) (items []*BaseFromCCFIndexList, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT * FROM base_from_ccf_index WHERE 1=1  `
+	if condition != "" {
+		sql += condition
+	}
+	sql += ` ORDER BY sort ASC, base_from_ccf_index_id asc`
+	_, err = o.Raw(sql, pars).QueryRows(&items)
+	return
+}
+
+func GetCCFIndexDataCount(indexCode string) (count int, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT COUNT(1) AS count FROM base_from_ccf_data WHERE index_code=? `
+	err = o.Raw(sql, indexCode).QueryRow(&count)
+	return
+}
+
+type CCFIndexDataCountGroup struct {
+	IndexCode string
+	Count     int
+}
+
+func GetCCFIndexDataCountGroup(indexCodes []string) (items []*CCFIndexDataCountGroup, err error) {
+	if len(indexCodes) <= 0 {
+		return
+	}
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT COUNT(1) AS count, index_code FROM base_from_ccf_data WHERE index_code IN (` + utils.GetOrmInReplace(len(indexCodes)) + `) GROUP BY index_code`
+	_, err = o.Raw(sql, indexCodes).QueryRows(&items)
+	return
+}
+
+func GetCCFIndexData(indexCode string, startSize, pageSize int) (items []*BaseFromCCFData, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT *  FROM base_from_ccf_data WHERE index_code=? ORDER BY data_time DESC LIMIT ?,? `
+	_, err = o.Raw(sql, indexCode, startSize, pageSize).QueryRows(&items)
+	return
+}
+
+func GetCCFIndexDataByCodes(indexCode []string) (items []*BaseFromCCFData, err error) {
+	if len(indexCode) <= 0 {
+		return
+	}
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT *  FROM base_from_ccf_data WHERE index_code in (` + utils.GetOrmInReplace(len(indexCode)) + `) ORDER BY data_time DESC  `
+	_, err = o.Raw(sql, indexCode).QueryRows(&items)
+	return
+}
+
+type BaseFromCCFData struct {
+	BaseFromCcfDataId  int `orm:"column(base_from_ccf_data_id);pk"`
+	BaseFromCcfIndexId int
+	IndexCode          string
+	DataTime           string
+	Value              string
+	CreateTime         string
+	ModifyTime         string
+	DataTimestamp      int64
+}
+
+type BaseFromCCFIndexSearchItem struct {
+	BaseFromCcfIndexId int `orm:"column(base_from_ccf_index_id);pk"`
+	ClassifyId         int
+	IndexCode          string
+	IndexName          string
+}
+
+// GetCCFItemList 模糊查询CCF数据库指标列表
+func GetCCFItemList(condition string) (items []*BaseFromCCFIndexSearchItem, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := "SELECT * FROM base_from_ccf_index WHERE 1=1"
+	if condition != "" {
+		sql += condition
+	}
+	_, err = o.Raw(sql).QueryRows(&items)
+	return
+}
+
+func GetCCFIndexDataByCode(indexCode string) (list []*BaseFromCCFData, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT * FROM base_from_ccf_data WHERE index_code=? `
+	_, err = o.Raw(sql, indexCode).QueryRows(&list)
+	return
+}
+
+func GetBaseFromCCFIndexByIndexCode(indexCode string) (list *BaseFromCCFIndex, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT * FROM base_from_ccf_index WHERE index_code=? `
+	err = o.Raw(sql, indexCode).QueryRow(&list)
+	return
+}

+ 55 - 0
models/data_manage/base_from_ccf_classify.go

@@ -0,0 +1,55 @@
+package data_manage
+
+import (
+	"eta/eta_api/utils"
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+// BaseFromCCFClassify CCF原始数据分类表
+type BaseFromCCFClassify struct {
+	BaseFromCcfClassifyId int       `orm:"column(base_from_ccf_classify_id);pk"`
+	ClassifyName          string    `description:"分类名称"`
+	ParentId              int       `description:"父级id"`
+	SysUserId             int       `description:"创建人id"`
+	SysUserRealName       string    `description:"创建人姓名"`
+	Level                 int       `description:"层级"`
+	Sort                  int       `description:"排序字段,越小越靠前,默认值:10"`
+	ModifyTime            time.Time `description:"修改时间"`
+	CreateTime            time.Time `description:"创建时间"`
+}
+
+// GetBaseFromCCFClassify 获取所有分类
+func GetBaseFromCCFClassify() (items []*BaseFromCCFClassify, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT * FROM base_from_ccf_classify ORDER BY parent_id ASC, sort ASC, base_from_ccf_classify_id ASC`
+	_, err = o.Raw(sql).QueryRows(&items)
+	return
+}
+
+// BaseFromCCFClassifyItem CCF数据分类信息
+type BaseFromCCFClassifyItem struct {
+	ClassifyId   int                        `description:"分类ID"`
+	ClassifyName string                     `description:"分类名称"`
+	ParentId     int                        `description:"父级id"`
+	Level        int                        `description:"层级"`
+	Sort         int                        `description:"排序字段"`
+	CreateTime   string                     `description:"创建时间"`
+	ModifyTime   string                     `description:"修改时间"`
+	Child        []*BaseFromCCFClassifyItem `description:"子分类"`
+}
+
+func (y *BaseFromCCFClassify) Format2Item(origin *BaseFromCCFClassify) (item *BaseFromCCFClassifyItem) {
+	if origin == nil {
+		return
+	}
+	item = new(BaseFromCCFClassifyItem)
+	item.ClassifyId = origin.BaseFromCcfClassifyId
+	item.ClassifyName = origin.ClassifyName
+	item.ParentId = origin.ParentId
+	item.Level = origin.Level
+	item.Sort = origin.Sort
+	item.CreateTime = utils.TimeTransferString(utils.FormatDateTime, origin.CreateTime)
+	item.ModifyTime = utils.TimeTransferString(utils.FormatDateTime, origin.ModifyTime)
+	return
+}

+ 155 - 0
models/data_manage/ccf_stock_classify.go

@@ -0,0 +1,155 @@
+package data_manage
+
+import (
+	"eta/eta_api/utils"
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
+	"strings"
+	"time"
+)
+
+// CCFStockClassify CCF化纤-装置分类
+type CCFStockClassify struct {
+	CcfStockClassifyId int       `orm:"column(ccf_stock_classify_id);pk"`
+	ClassifyName       string    `description:"分类名称"`
+	CreateTime         time.Time `description:"创建时间"`
+	ModifyTime         time.Time `description:"修改时间"`
+}
+
+func (m *CCFStockClassify) TableName() string {
+	return "ccf_stock_classify"
+}
+
+type CCFStockClassifyCols struct {
+	CcfStockClassifyId string
+	ClassifyName       string
+	CreateTime         string
+	ModifyTime         string
+}
+
+func (m *CCFStockClassify) Cols() CCFStockClassifyCols {
+	return CCFStockClassifyCols{
+		CcfStockClassifyId: "ccf_stock_classify_id",
+		ClassifyName:       "classify_name",
+		CreateTime:         "create_time",
+		ModifyTime:         "modify_time",
+	}
+}
+
+func (m *CCFStockClassify) PrimaryId() string {
+	return m.Cols().CcfStockClassifyId
+}
+
+func (m *CCFStockClassify) Create() (err error) {
+	o := orm.NewOrmUsingDB("data")
+	id, err := o.Insert(m)
+	if err != nil {
+		return
+	}
+	m.CcfStockClassifyId = int(id)
+	return
+}
+
+func (m *CCFStockClassify) CreateMulti(items []*CCFStockClassify) (err error) {
+	if len(items) == 0 {
+		return
+	}
+	o := orm.NewOrmUsingDB("data")
+	_, err = o.InsertMulti(len(items), items)
+	return
+}
+
+func (m *CCFStockClassify) Update(cols []string) (err error) {
+	o := orm.NewOrmUsingDB("data")
+	_, err = o.Update(m, cols...)
+	return
+}
+
+func (m *CCFStockClassify) Del() (err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.PrimaryId())
+	_, err = o.Raw(sql, m.CcfStockClassifyId).Exec()
+	return
+}
+
+func (m *CCFStockClassify) MultiDel(menuIds []int) (err error) {
+	if len(menuIds) == 0 {
+		return
+	}
+	o := orm.NewOrmUsingDB("data")
+	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s IN (%s)`, m.TableName(), m.PrimaryId(), utils.GetOrmInReplace(len(menuIds)))
+	_, err = o.Raw(sql, menuIds).Exec()
+	return
+}
+
+func (m *CCFStockClassify) GetItemById(id int) (item *CCFStockClassify, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.PrimaryId())
+	err = o.Raw(sql, id).QueryRow(&item)
+	return
+}
+
+func (m *CCFStockClassify) GetItemByCondition(condition string, pars []interface{}, orderRule string) (item *CCFStockClassify, err error) {
+	o := orm.NewOrmUsingDB("data")
+	order := ``
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE 1=1 %s %s LIMIT 1`, m.TableName(), condition, order)
+	err = o.Raw(sql, pars).QueryRow(&item)
+	return
+}
+
+func (m *CCFStockClassify) GetCountByCondition(condition string, pars []interface{}) (count int, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := fmt.Sprintf(`SELECT COUNT(1) FROM %s WHERE 1=1 %s`, m.TableName(), condition)
+	err = o.Raw(sql, pars).QueryRow(&count)
+	return
+}
+
+func (m *CCFStockClassify) GetItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string) (items []*CCFStockClassify, err error) {
+	o := orm.NewOrmUsingDB("data")
+	fields := strings.Join(fieldArr, ",")
+	if len(fieldArr) == 0 {
+		fields = `*`
+	}
+	order := fmt.Sprintf(`ORDER BY %s DESC`, m.Cols().CreateTime)
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT %s FROM %s WHERE 1=1 %s %s`, fields, m.TableName(), condition, order)
+	_, err = o.Raw(sql, pars).QueryRows(&items)
+	return
+}
+
+func (m *CCFStockClassify) GetPageItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string, startSize, pageSize int) (items []*CCFStockClassify, err error) {
+	o := orm.NewOrmUsingDB("data")
+	fields := strings.Join(fieldArr, ",")
+	if len(fieldArr) == 0 {
+		fields = `*`
+	}
+	order := fmt.Sprintf(`ORDER BY %s DESC`, m.Cols().CreateTime)
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT %s FROM %s WHERE 1=1 %s %s LIMIT ?,?`, fields, m.TableName(), condition, order)
+	_, err = o.Raw(sql, pars, startSize, pageSize).QueryRows(&items)
+	return
+}
+
+// CCFStockClassifyItem CCF化纤-装置分类
+type CCFStockClassifyItem struct {
+	ClassifyId   int    `description:"分类ID"`
+	ClassifyName string `description:"分类名称"`
+	CreateTime   string `description:"创建时间"`
+	ModifyTime   string `description:"修改时间"`
+}
+
+func (m *CCFStockClassify) Format2Item() (item *CCFStockClassifyItem) {
+	item = new(CCFStockClassifyItem)
+	item.ClassifyId = m.CcfStockClassifyId
+	item.ClassifyName = m.ClassifyName
+	item.CreateTime = utils.TimeTransferString(utils.FormatDateTime, m.CreateTime)
+	item.ModifyTime = utils.TimeTransferString(utils.FormatDateTime, m.ModifyTime)
+	return
+}

+ 171 - 0
models/data_manage/ccf_stock_excel.go

@@ -0,0 +1,171 @@
+package data_manage
+
+import (
+	"eta/eta_api/utils"
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
+	"html"
+	"regexp"
+	"strings"
+	"time"
+)
+
+// CCFStockExcel CCF化纤装置表格
+type CCFStockExcel struct {
+	CcfStockExcelId int       `orm:"column(ccf_stock_excel_id);pk"`
+	ClassifyId      int       `description:"分类ID"`
+	ExcelDate       time.Time `description:"表格日期"`
+	ExcelContent    string    `description:"表格HTML"`
+	FromPage        string    `description:"表格来源"`
+	CreateTime      time.Time `description:"创建时间"`
+	ModifyTime      time.Time `description:"修改时间"`
+}
+
+func (m *CCFStockExcel) TableName() string {
+	return "ccf_stock_excel"
+}
+
+type CCFStockExcelCols struct {
+	CcfStockExcelId string
+	ClassifyId      string
+	ExcelDate       string
+	ExcelContent    string
+	FromPage        string
+	CreateTime      string
+	ModifyTime      string
+}
+
+func (m *CCFStockExcel) Cols() CCFStockExcelCols {
+	return CCFStockExcelCols{
+		CcfStockExcelId: "ccf_stock_excel_id",
+		ClassifyId:      "classify_id",
+		ExcelDate:       "excel_date",
+		ExcelContent:    "excel_content",
+		FromPage:        "from_page",
+		CreateTime:      "create_time",
+		ModifyTime:      "modify_time",
+	}
+}
+
+func (m *CCFStockExcel) PrimaryId() string {
+	return m.Cols().CcfStockExcelId
+}
+
+func (m *CCFStockExcel) Create() (err error) {
+	o := orm.NewOrmUsingDB("data")
+	id, err := o.Insert(m)
+	if err != nil {
+		return
+	}
+	m.CcfStockExcelId = int(id)
+	return
+}
+
+func (m *CCFStockExcel) CreateMulti(items []*CCFStockExcel) (err error) {
+	if len(items) == 0 {
+		return
+	}
+	o := orm.NewOrmUsingDB("data")
+	_, err = o.InsertMulti(len(items), items)
+	return
+}
+
+func (m *CCFStockExcel) Update(cols []string) (err error) {
+	o := orm.NewOrmUsingDB("data")
+	_, err = o.Update(m, cols...)
+	return
+}
+
+func (m *CCFStockExcel) Del() (err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.PrimaryId())
+	_, err = o.Raw(sql, m.CcfStockExcelId).Exec()
+	return
+}
+
+func (m *CCFStockExcel) MultiDel(menuIds []int) (err error) {
+	if len(menuIds) == 0 {
+		return
+	}
+	o := orm.NewOrmUsingDB("data")
+	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s IN (%s)`, m.TableName(), m.PrimaryId(), utils.GetOrmInReplace(len(menuIds)))
+	_, err = o.Raw(sql, menuIds).Exec()
+	return
+}
+
+func (m *CCFStockExcel) GetItemById(id int) (item *CCFStockExcel, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.PrimaryId())
+	err = o.Raw(sql, id).QueryRow(&item)
+	return
+}
+
+func (m *CCFStockExcel) GetItemByCondition(condition string, pars []interface{}, orderRule string) (item *CCFStockExcel, err error) {
+	o := orm.NewOrmUsingDB("data")
+	order := ``
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE 1=1 %s %s LIMIT 1`, m.TableName(), condition, order)
+	err = o.Raw(sql, pars).QueryRow(&item)
+	return
+}
+
+func (m *CCFStockExcel) GetCountByCondition(condition string, pars []interface{}) (count int, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := fmt.Sprintf(`SELECT COUNT(1) FROM %s WHERE 1=1 %s`, m.TableName(), condition)
+	err = o.Raw(sql, pars).QueryRow(&count)
+	return
+}
+
+func (m *CCFStockExcel) GetItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string) (items []*CCFStockExcel, err error) {
+	o := orm.NewOrmUsingDB("data")
+	fields := strings.Join(fieldArr, ",")
+	if len(fieldArr) == 0 {
+		fields = `*`
+	}
+	order := fmt.Sprintf(`ORDER BY %s DESC`, m.Cols().CreateTime)
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT %s FROM %s WHERE 1=1 %s %s`, fields, m.TableName(), condition, order)
+	_, err = o.Raw(sql, pars).QueryRows(&items)
+	return
+}
+
+func (m *CCFStockExcel) GetPageItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string, startSize, pageSize int) (items []*CCFStockExcel, err error) {
+	o := orm.NewOrmUsingDB("data")
+	fields := strings.Join(fieldArr, ",")
+	if len(fieldArr) == 0 {
+		fields = `*`
+	}
+	order := fmt.Sprintf(`ORDER BY %s DESC`, m.Cols().CreateTime)
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT %s FROM %s WHERE 1=1 %s %s LIMIT ?,?`, fields, m.TableName(), condition, order)
+	_, err = o.Raw(sql, pars, startSize, pageSize).QueryRows(&items)
+	return
+}
+
+type CCFStockExcelItem struct {
+	ExcelId      int    `description:"表格ID"`
+	ClassifyId   int    `description:"分类ID"`
+	ExcelDate    string `description:"表格日期"`
+	ExcelContent string `description:"表格HTML"`
+	CreateTime   string `description:"创建时间"`
+	ModifyTime   string `description:"修改时间"`
+}
+
+func (m *CCFStockExcel) Format2Item() (item *CCFStockExcelItem) {
+	item = new(CCFStockExcelItem)
+	item.ExcelId = m.CcfStockExcelId
+	item.ClassifyId = m.ClassifyId
+	item.ExcelDate = utils.TimeTransferString(utils.FormatDate, m.ExcelDate)
+	content := html.UnescapeString(m.ExcelContent)
+	content = regexp.MustCompile(`\n`).ReplaceAllString(content, "")
+	item.ExcelContent = html.UnescapeString(content)
+	item.CreateTime = utils.TimeTransferString(utils.FormatDateTime, m.CreateTime)
+	item.ModifyTime = utils.TimeTransferString(utils.FormatDateTime, m.ModifyTime)
+	return
+}

+ 9 - 0
models/data_manage/chart_edb_mapping.go

@@ -210,6 +210,15 @@ func GetChartEdbMappingByEdbInfoId(edbInfoId int) (item *ChartEdbInfoMapping, er
 	return
 }
 
+// GetEdbMappingListByEdbInfoId 根据指标id获取edb_mapping
+func GetEdbMappingListByEdbInfoId(edbInfoId int) (item []*ChartEdbInfoMapping, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT * FROM chart_edb_mapping
+			 WHERE edb_info_id = ? limit 1`
+	_, err = o.Raw(sql, edbInfoId).QueryRows(&item)
+	return
+}
+
 // GetChartEdbMappingByFutureGoodEdbInfoId 根据指标id获取edb_mapping
 func GetChartEdbMappingByFutureGoodEdbInfoId(edbInfoId int) (item *ChartEdbInfoMapping, err error) {
 	o := orm.NewOrmUsingDB("data")

+ 4 - 4
models/data_manage/chart_info.go

@@ -1763,10 +1763,10 @@ func GetChartInfoByClassifyIdAndName(classifyId int, chartName string) (item *Ch
 
 // BatchChartRefreshReq 批量刷新图表请求
 type BatchChartRefreshReq struct {
-	ChartInfoCode   []string `description:"图表编码数组"`
-	ReportId        int      `description:"报告id"`
-	ReportChapterId int      `description:"报告章节id"`
-	Source          string   `description:"来源,枚举值:report、english_report、smart_report"`
+	ChartInfoCode []string `description:"图表编码数组"`
+	PrimaryId     int      `description:"研报/智能研报/PPT主键"`
+	SubId         int      `description:"报告章节ID"`
+	Source        string   `description:"来源,枚举值:report、english_report、smart_report、ppt"`
 }
 
 // GetChartInfoListByUniqueCodeSlice 根据图表编码获取图表列表数据

+ 16 - 0
models/data_manage/cross_variety/chart_info_cross_variety.go

@@ -72,6 +72,22 @@ func GetChartInfoCrossVarietyByChartInfoId(id int) (item *ChartInfoCrossVariety,
 	return
 }
 
+func GetChartInfoCrossVarietyByXEdbInfoId(edbInfoId int) (items []*ChartInfoCrossVariety, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT a.* FROM chart_info_cross_variety a 
+         join chart_tag_variety b on a.chart_x_tag_id=b.chart_tag_id WHERE b.edb_info_id = ? `
+	_, err = o.Raw(sql, edbInfoId).QueryRows(&items)
+	return
+}
+
+func GetChartInfoCrossVarietyByYEdbInfoId(edbInfoId int) (items []*ChartInfoCrossVariety, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT a.* FROM chart_info_cross_variety a 
+         join chart_tag_variety b on a.chart_y_tag_id=b.chart_tag_id WHERE b.edb_info_id = ? `
+	_, err = o.Raw(sql, edbInfoId).QueryRows(&items)
+	return
+}
+
 // CreateChart
 // @Description: 新增跨品种图表
 // @author: Roc

+ 11 - 0
models/data_manage/cross_variety/chart_tag_variety.go

@@ -260,3 +260,14 @@ func GetChartTagVarietyListByTagIdList(chartTagIdList []int) (items []*ChartTagV
 
 	return
 }
+
+func DeleteChartTagVarietyByEdbInfoId(edbInfoId int) (err error) {
+	// 删除不存在的品种
+	o := orm.NewOrmUsingDB("data")
+	sql := ` DELETE FROM chart_tag_variety WHERE edb_info_id=?`
+	_, err = o.Raw(sql, edbInfoId, edbInfoId).Exec()
+	if err != nil {
+		return
+	}
+	return
+}

+ 13 - 3
models/data_manage/edb_classify.go

@@ -298,10 +298,20 @@ type EdbClassifyListResp struct {
 }
 
 type ClassifyDeleteCheckResp struct {
-	DeleteStatus int    `description:"检测状态:0:默认值,如果为0,继续走其他校验,1:若目录关联指标不可删除,2:确认删除当前目录及包含的子目录吗,3:当前指标已用作画图,不可删除"`
-	TipsMsg      string `description:"提示信息"`
+	DeleteStatus int              `description:"检测状态:0:默认值,如果为0,继续走其他校验,1:若目录关联指标不可删除,2:确认删除当前目录及包含的子目录吗,3:当前指标已用作画图,不可删除"`
+	TipsMsg      string           `description:"提示信息"`
+	TableList    []*ExcelBaseInfo `description:"关联的表格"`
+}
+type ExcelBaseInfo struct {
+	ExcelInfoId     int    `orm:"column(excel_info_id);pk"`
+	Source          int    `description:"表格来源,1:excel插件的表格,2:自定义表格,3:混合表格,4:自定义分析,默认:1"`
+	ExcelType       int    `description:"表格类型,1:指标列,2:日期列,默认:1"`
+	ExcelName       string `description:"表格名称"`
+	UniqueCode      string `description:"表格唯一编码"`
+	ExcelClassifyId int    `description:"表格分类id"`
+	//SysUserId       int    `description:"操作人id"`
+	//SysUserRealName string `description:"操作人真实姓名"`
 }
-
 type ClassifyDeleteCheckReq struct {
 	ClassifyId int `description:"分类id"`
 	EdbInfoId  int `description:"指标id"`

+ 138 - 1
models/data_manage/edb_info.go

@@ -1,6 +1,8 @@
 package data_manage
 
 import (
+	"encoding/json"
+	"eta/eta_api/models/data_manage/line_equation/request"
 	"eta/eta_api/models/mgo"
 	"eta/eta_api/services/alarm_msg"
 	"eta/eta_api/utils"
@@ -8,6 +10,7 @@ import (
 	"github.com/beego/beego/v2/client/orm"
 	"github.com/rdlucklib/rdluck_tools/paging"
 	"go.mongodb.org/mongo-driver/bson"
+	"strconv"
 	"strings"
 	"time"
 )
@@ -247,10 +250,21 @@ func DeleteEdbInfoAndData(edbInfoId, source, subSource int) (err error) {
 	// 删除计算指标的关系
 	sql = ` DELETE FROM edb_info_calculate_mapping WHERE edb_info_id=? `
 	_, err = to.Raw(sql, edbInfoId).Exec()
-
+	if err != nil {
+		return
+	}
 	// 删除预测指标的配置
 	sql = ` DELETE FROM predict_edb_conf WHERE predict_edb_info_id=? `
 	_, err = to.Raw(sql, edbInfoId).Exec()
+	if err != nil {
+		return
+	}
+	// 删除跨品种分析标签绑定的指标
+	sql = ` DELETE FROM chart_tag_variety WHERE edb_info_id=?`
+	_, err = to.Raw(sql, edbInfoId).Exec()
+	if err != nil {
+		return
+	}
 	return
 }
 
@@ -856,7 +870,123 @@ func ReplaceChartEdb(oldEdbInfo, newEdbInfo *EdbInfo) (relationEdbInfoIdList []i
 			return
 		}
 		replaceChartTotal = len(chartEdbMappingList)
+		// 查询所有的相关的图表信息
+		chartInfoIds := make([]string, 0)
+		if len(chartEdbMappingList) > 0 {
+			for _, chartEdbMapping := range chartEdbMappingList {
+				chartInfoIds = append(chartInfoIds, strconv.Itoa(chartEdbMapping.ChartInfoId))
+			}
+		}
 
+		if len(chartInfoIds) > 0 {
+			chartInfoList, e := GetChartInfoListByChartIdList(chartInfoIds)
+			if e != nil {
+				err = e
+				errmsg = "获取图表信息失败:Err:" + e.Error()
+				return
+			}
+			for _, chartInfo := range chartInfoList {
+				updateStr := make([]string, 0)
+				if chartInfo.EdbInfoIds != "" && strings.Contains(chartInfo.EdbInfoIds, strconv.Itoa(oldEdbInfo.EdbInfoId)) {
+					//需要更换
+					//解析字符串
+					edbInfoIds := strings.Split(chartInfo.EdbInfoIds, ",")
+					for i, edbInfoId := range edbInfoIds {
+						if edbInfoId == strconv.Itoa(oldEdbInfo.EdbInfoId) {
+							edbInfoIds[i] = strconv.Itoa(newEdbInfo.EdbInfoId)
+						}
+					}
+					chartInfo.EdbInfoIds = strings.Join(edbInfoIds, ",")
+					updateStr = append(updateStr, "EdbInfoIds")
+				}
+				if chartInfo.ExtraConfig != "" {
+					//判断是否是拟合方程或者散点图截面图
+					if chartInfo.Source == utils.CHART_SOURCE_LINE_EQUATION {
+						//解析配置内容
+						var lineChartInfoConfig request.LineChartInfoReq
+						err = json.Unmarshal([]byte(chartInfo.ExtraConfig), &lineChartInfoConfig)
+						if err != nil {
+							errmsg = "获取图表配置信息失败 json.Unmarshal:Err:" + err.Error()
+							return
+						}
+						xEdbInfoIdList := lineChartInfoConfig.XEdbInfoIdList
+						yEdbInfoIdList := lineChartInfoConfig.YEdbInfoIdList
+						if len(xEdbInfoIdList) > 0 {
+							// 循环判断是否存在
+							for k, xEdbInfoId := range xEdbInfoIdList {
+								if xEdbInfoId == oldEdbInfo.EdbInfoId {
+									xEdbInfoIdList[k] = newEdbInfo.EdbInfoId
+								}
+							}
+						}
+						if len(yEdbInfoIdList) > 0 {
+							// 循环判断是否存在
+							for k, yEdbInfoId := range yEdbInfoIdList {
+								if yEdbInfoId == oldEdbInfo.EdbInfoId {
+									yEdbInfoIdList[k] = newEdbInfo.EdbInfoId
+								}
+							}
+						}
+						// 替换新的指标信息
+						lineChartInfoConfig.XEdbInfoIdList = xEdbInfoIdList
+						lineChartInfoConfig.YEdbInfoIdList = yEdbInfoIdList
+						// 重新序列化
+						lineChartInfoConfigJson, e := json.Marshal(lineChartInfoConfig)
+						if e != nil {
+							err = e
+							errmsg = "图表配置信息序列化失败:json.Marshal Err: " + e.Error()
+							return
+						}
+						lineChartInfoConfigStr := string(lineChartInfoConfigJson)
+						// 更新图表配置信息
+						chartInfo.ExtraConfig = lineChartInfoConfigStr
+						updateStr = append(updateStr, "ExtraConfig")
+					} else if chartInfo.ChartType == utils.CHART_TYPE_SECTION_SCATTER {
+						//解析配置内容
+						var tmpExtraConfig SectionScatterReq
+						err = json.Unmarshal([]byte(chartInfo.ExtraConfig), &tmpExtraConfig)
+						if err != nil {
+							errmsg = "获取截面散点图配置信息失败 json.Unmarshal:Err:" + err.Error()
+							return
+						}
+						//找到指标信息,并替换
+						if len(tmpExtraConfig.SeriesList) > 0 {
+							for k1, series := range tmpExtraConfig.SeriesList {
+								for k2, item := range series.EdbInfoList {
+									if item.XEdbInfoId == oldEdbInfo.EdbInfoId {
+										tmpExtraConfig.SeriesList[k1].EdbInfoList[k2].XEdbInfoId = newEdbInfo.EdbInfoId
+									}
+									if item.YEdbInfoId == oldEdbInfo.EdbInfoId {
+										tmpExtraConfig.SeriesList[k1].EdbInfoList[k2].YEdbInfoId = newEdbInfo.EdbInfoId
+									}
+								}
+							}
+						}
+						// 重新序列化
+						sectionScatterConfigJson, e := json.Marshal(tmpExtraConfig)
+						if e != nil {
+							err = e
+							errmsg = "图表配置信息序列化失败:json.Marshal Err: " + e.Error()
+							return
+						}
+						sectionScatterConfigStr := string(sectionScatterConfigJson)
+						// 更新图表配置信息
+						chartInfo.ExtraConfig = sectionScatterConfigStr
+						updateStr = append(updateStr, "ExtraConfig")
+					}
+				}
+				if len(updateStr) > 0 {
+					updateStr = append(updateStr, "ModifyTime")
+					chartInfo.ModifyTime = time.Now()
+					err = chartInfo.Update(updateStr)
+					if err != nil {
+						errmsg = "更新图表信息失败:chartInfo.Update Err: " + err.Error()
+						return
+					}
+				}
+			}
+		}
+		// 查询所有的图表信息
 		if len(chartEdbMappingList) > 0 {
 			chartInfoIdList := make([]string, 0)
 			for _, mv := range chartEdbMappingList {
@@ -868,6 +998,8 @@ func ReplaceChartEdb(oldEdbInfo, newEdbInfo *EdbInfo) (relationEdbInfoIdList []i
 					errmsg = "获取图表所有指标信息失败:Err:" + err.Error()
 					return
 				}
+				// 查询图表信息
+
 				var minData, maxData float64
 				minData = newEdbInfo.MinValue
 				maxData = newEdbInfo.MaxValue
@@ -1686,3 +1818,8 @@ func GetEdbInfoByClassifyIdAndSource(classifyId, edbInfoType, source int) (items
 	_, err = o.Raw(sql, pars).QueryRows(&items)
 	return
 }
+
+type ReplaceEdbInfoItem struct {
+	OldEdbInfo *EdbInfo
+	NewEdbInfo *EdbInfo
+}

+ 32 - 2
models/data_manage/excel/excel_edb_mapping.go

@@ -31,12 +31,19 @@ func (e *ExcelEdbMapping) Add() (err error) {
 	return
 }
 
+// Update 更新 excel表格基础信息
+func (e *ExcelEdbMapping) Update(cols []string) (err error) {
+	o := orm.NewOrmUsingDB("data")
+	_, err = o.Update(e, cols...)
+	return
+}
+
 // GetExcelEdbMappingByEdbInfoId 根据指标id获取配置关系
-func GetExcelEdbMappingByEdbInfoId(edbInfoId int) (item *ExcelEdbMapping, err error) {
+func GetExcelEdbMappingByEdbInfoId(edbInfoId int) (items []*ExcelEdbMapping, err error) {
 	o := orm.NewOrmUsingDB("data")
 	sql := ` SELECT *  FROM excel_edb_mapping WHERE 1=1 AND edb_info_id = ? `
 
-	err = o.Raw(sql, edbInfoId).QueryRow(&item)
+	_, err = o.Raw(sql, edbInfoId).QueryRows(&items)
 	return
 }
 
@@ -89,6 +96,20 @@ func GetNoCustomAnalysisExcelEdbMappingCount(edbInfoId int) (count int, err erro
 	return
 }
 
+type ExcelEdbMappingWithParentIdItem struct {
+	ExcelInfoId int
+	ParentId    int
+}
+
+func GetNoCustomAnalysisExcelEdbMapping(edbInfoId int) (items []ExcelEdbMappingWithParentIdItem, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT b.excel_info_id, b.parent_id FROM excel_edb_mapping a 
+                          join excel_info b on a.excel_info_id=b.excel_info_id
+                          WHERE edb_info_id=? AND a.source != 4 AND b.is_delete = 0`
+	_, err = o.Raw(sql, edbInfoId).QueryRows(&items)
+	return
+}
+
 // GetAllExcelEdbMappingByExcelInfoId 根据excel的id获取所有的指标
 func GetAllExcelEdbMappingByExcelInfoId(excelInfoId int) (items []*ExcelEdbMapping, err error) {
 	o := orm.NewOrmUsingDB("data")
@@ -98,6 +119,15 @@ func GetAllExcelEdbMappingByExcelInfoId(excelInfoId int) (items []*ExcelEdbMappi
 	return
 }
 
+// GetExcelEdbMappingByEdbInfoIdAndSource 根据指标id获取配置关系
+func GetExcelEdbMappingByEdbInfoIdAndSource(edbInfoId int, sources []int) (items []*ExcelEdbMapping, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT *  FROM excel_edb_mapping WHERE 1=1 AND edb_info_id = ? AND source in (` + utils.GetOrmInReplace(len(sources)) + `) `
+
+	_, err = o.Raw(sql, edbInfoId, sources).QueryRows(&items)
+	return
+}
+
 // DeleteCustomAnalysisExcelEdbMappingByEdbInfoId
 // @Description: 根据指标id删除与自定义分析表格的关系
 // @author: Roc

+ 74 - 4
models/data_manage/excel/excel_info.go

@@ -1,9 +1,11 @@
 package excel
 
 import (
+	"eta/eta_api/models/data_manage"
 	"eta/eta_api/utils"
 	"fmt"
 	"github.com/beego/beego/v2/client/orm"
+	"strconv"
 	"time"
 )
 
@@ -615,10 +617,10 @@ func SaveExcelInfoAndSheet(excelInfo *ExcelInfo, updateExcelInfoParam []string,
 
 // BatchRefreshExcelReq 批量刷新表格请求
 type BatchRefreshExcelReq struct {
-	ExcelCodes      []string `description:"表格编码"`
-	ReportId        int      `description:"报告ID"`
-	ReportChapterId int      `description:"报告章节ID"`
-	Source          string   `description:"来源,枚举值:report、english_report、smart_report"`
+	ExcelCodes []string `description:"表格编码"`
+	PrimaryId  int      `description:"研报/智能研报/PPT主键"`
+	SubId      int      `description:"报告章节ID"`
+	Source     string   `description:"来源,枚举值:report、english_report、smart_report"`
 }
 
 // GetExcelMaxSortByClassifyId 获取当前分类下,且排序数最大的excel
@@ -713,6 +715,74 @@ func ModifyExcelInfoUserIdByOldUserId(oldUserIdList []int, userId int, userName
 	return
 }
 
+func GetExcelBaseInfoByExcelInfoIdList(excelInfoIdList []int) (items []*data_manage.ExcelBaseInfo, err error) {
+	num := len(excelInfoIdList)
+	if num <= 0 {
+		return
+	}
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT excel_info_id,source,excel_type,excel_name,unique_code,excel_classify_id,sys_user_id,sys_user_real_name FROM excel_info WHERE excel_info_id in (` + utils.GetOrmInReplace(num) + `) order by excel_info_id DESC `
+	_, err = o.Raw(sql, excelInfoIdList).QueryRows(&items)
+
+	return
+}
+
+// ReplaceEdbInExcel 替换表格中的指标
+func ReplaceEdbInExcel(oldEdbInfoId, newEdbInfoId int, updateExcelList []*ExcelInfo) (err error) {
+	var errmsg string
+	logMsg := `` // 记录替换的日志
+	replaceTotal := 0
+	o := orm.NewOrmUsingDB("data")
+	to, err := o.Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = to.Rollback()
+		} else {
+			_ = to.Commit()
+			if logMsg != `` {
+				utils.FileLog.Info(fmt.Sprintf("替换表格中的指标记录,替换总表格数:%d,旧的指标id:%d,新的指标id:%d;%s", replaceTotal, oldEdbInfoId, newEdbInfoId, logMsg))
+			}
+		}
+		if errmsg != "" {
+			fmt.Println("errmsg:" + errmsg)
+		}
+		if err != nil && errmsg != "" {
+			//go alarm_msg.SendAlarmMsg("替换替换配置中的指标记录失败提醒,errmsg:"+errmsg, 3)
+		}
+	}()
+	// 替换表格中的内容
+	for _, excelInfo := range updateExcelList {
+		//更新配置中的指标A
+		sql := `UPDATE excel_info SET content=?, modify_time=? WHERE excel_info_id=?`
+		_, err = to.Raw(sql, excelInfo.Content, time.Now(), excelInfo.ExcelInfoId).Exec()
+		if err != nil {
+			errmsg = "更新表格内容失败:Err:" + err.Error()
+			return
+		}
+		//更新配置中的指标B
+		// 判断是否已存在绑定,如果存在则删除
+		sql = `DELETE FROM excel_edb_mapping WHERE excel_info_id=? and edb_info_id=?`
+		_, err = to.Raw(sql, excelInfo.ExcelInfoId, newEdbInfoId).Exec()
+		if err != nil {
+			errmsg = "删除指标B关联图表配置信息失败:Err:" + err.Error()
+			return
+		}
+		// 插入新的绑定
+		sql = `UPDATE excel_edb_mapping SET edb_info_id=?, modify_time=? WHERE excel_info_id=? and edb_info_id=?`
+		_, err = to.Raw(sql, newEdbInfoId, time.Now(), excelInfo.ExcelInfoId, oldEdbInfoId).Exec()
+		if err != nil {
+			errmsg = "更新指标B关联图表配置信息失败:Err:" + err.Error()
+			return
+		}
+		logMsg += `涉及到的表格id:` + strconv.Itoa(excelInfo.ExcelInfoId) + ";"
+		replaceTotal += 1
+	}
+	return
+}
+
 // GetChildExcelInfoByParentId 根据id 获取eta表格详情
 func GetChildExcelInfoByParentId(parentId int) (items []*ExcelInfo, err error) {
 	o := orm.NewOrmUsingDB("data")

+ 40 - 0
models/data_manage/excel/request/time_table.go

@@ -0,0 +1,40 @@
+package request
+
+// TimeTableDataConfig
+// @Description: 表格配置
+type TimeTableDataConfig struct {
+	EdbInfoIdList    []int                 `description:"指标id列表,从左至右,从上到下的顺序"`
+	Sort             int                   `description:"日期排序,0:倒序,1:正序"`
+	Data             []TimeTableManualData `description:"数据列表"`
+	Num              int                   `description:"实际数据需要列出来的期数"`
+	RemoveDate       []string              `description:"不展示的日期"`
+	ManualDate       []string              `description:"手动配置的日期(未来的日期)"`
+	TableEdbInfoList []TimeTableEdbInfo    `description:"表格内指标信息"`
+	TextRowData      [][]ManualDataReq     `description:"文本列表"`
+}
+
+// TimeTableEdbInfo
+// @Description: 表格指标信息
+type TimeTableEdbInfo struct {
+	EdbInfoId    int    `description:"指标ID"`
+	Tag          string `description:"标签"`
+	EdbName      string `description:"指标名称"`
+	EdbNameEn    string `description:"英文指标名称"`
+	EdbAliasName string `description:"指标别名"`
+	Frequency    string `description:"频度"`
+	Unit         string `description:"单位"`
+	UnitEn       string `description:"英文单位"`
+}
+
+// ManualData
+// @Description: 手工文本配置
+type TimeTableManualData struct {
+	DataType            int               `description:"数据类型,1:普通的,2:插值法,3:手动输入,4:公式计算"`
+	DataTime            string            `description:"所属日期"`
+	DataTimeType        int               `description:"日期类型,1:实际日期;2:未来日期"`
+	ShowValue           string            `description:"展示值"`
+	Value               string            `description:"实际值(计算公式)"`
+	EdbInfoId           int               `description:"指标id"`
+	Tag                 string            `description:"下标"`
+	RelationEdbInfoList []RelationEdbInfo `description:"关联指标(计算公式中关联的指标,用于计算的时候去匹配)"`
+}

+ 126 - 0
models/data_manage/multiple_graph_config.go

@@ -1,7 +1,14 @@
 package data_manage
 
 import (
+	"encoding/json"
+	"eta/eta_api/models/data_manage/line_equation/request"
+	"eta/eta_api/services/alarm_msg"
+	"eta/eta_api/utils"
+	"fmt"
 	"github.com/beego/beego/v2/client/orm"
+	"strconv"
+	"strings"
 	"time"
 )
 
@@ -80,3 +87,122 @@ type RollingCorrelationConfig struct {
 	CalculateValue int    `description:"计算窗口"`
 	CalculateUnit  string `description:"计算频度"`
 }
+
+// ReplaceEdbInfoInLineEquationMultipleGraphConfig 获取拟合方程配置
+func ReplaceEdbInfoInLineEquationMultipleGraphConfig(oldEdbInfo, newEdbInfo *EdbInfo) (replaceConfigTotal int, err error) {
+	var errmsg string
+	logMsg := `` // 记录替换的日志
+
+	o := orm.NewOrmUsingDB("data")
+	to, err := o.Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = to.Rollback()
+		} else {
+			_ = to.Commit()
+			if logMsg != `` {
+				utils.FileLog.Info(fmt.Sprintf("替换拟合方程中的指标记录 替换总数%d,旧的指标id:%d,新的指标id:%d;%s", replaceConfigTotal, oldEdbInfo.EdbInfoId, newEdbInfo.EdbInfoId, logMsg))
+			}
+		}
+		if errmsg != "" {
+			fmt.Println("errmsg:" + errmsg)
+		}
+		if err != nil && errmsg != "" {
+			go alarm_msg.SendAlarmMsg("替换拟合方程中的指标记录失败提醒,errmsg:"+errmsg, 3)
+		}
+	}()
+	//替换multiple_graph_config中的指标
+	{
+		multipleGraphConfigList := make([]*MultipleGraphConfig, 0)
+		csql := `SELECT * FROM multiple_graph_config WHERE edb_info_id_a=0 AND edb_info_id_b=0 AND curve !=""`
+		_, err = to.Raw(csql).QueryRows(&multipleGraphConfigList)
+		if err != nil {
+			errmsg = "获取指标关联图表配置信息失败:Err:" + err.Error()
+			return
+		}
+		if len(multipleGraphConfigList) == 0 {
+			return
+		}
+		updateList := make([]*MultipleGraphConfig, 0)
+		configIds := make([]int, 0)
+		configIdStr := make([]string, 0)
+		for _, mv := range multipleGraphConfigList {
+			if !strings.Contains(mv.Curve, strconv.Itoa(oldEdbInfo.EdbInfoId)) {
+				continue
+			}
+			//解析curve内容
+			var lineChartInfoConfig request.LineChartInfoReq
+			if err = json.Unmarshal([]byte(mv.Curve), &lineChartInfoConfig); err != nil {
+				errmsg = "获取跨品种分析配置信息失败:Err:" + err.Error()
+				return
+			}
+			updateFlag := false
+			// 遍历跨品种配置里的指标列表
+			for k, edbInfoId := range lineChartInfoConfig.XEdbInfoIdList {
+				if edbInfoId == oldEdbInfo.EdbInfoId {
+					updateFlag = true
+					lineChartInfoConfig.XEdbInfoIdList[k] = newEdbInfo.EdbInfoId
+				}
+			}
+			for k, edbInfoId := range lineChartInfoConfig.YEdbInfoIdList {
+				if edbInfoId == oldEdbInfo.EdbInfoId {
+					updateFlag = true
+					lineChartInfoConfig.YEdbInfoIdList[k] = newEdbInfo.EdbInfoId
+				}
+			}
+			if !updateFlag {
+				continue
+			}
+			newCurve, _ := json.Marshal(lineChartInfoConfig)
+			mv.Curve = string(newCurve)
+			//判断如果达到1000个数,则执行更新语句
+			updateList = append(updateList, mv)
+			configIds = append(configIds, mv.MultipleGraphConfigId)
+			configIdStr = append(configIdStr, strconv.Itoa(mv.MultipleGraphConfigId))
+			if len(configIds) >= 10 {
+				numStr := utils.GetOrmInReplace(len(configIds))
+				// 准备批量更新的 SQL 语句
+				updateSQL := `UPDATE multiple_graph_config SET   
+    curve = CASE multiple_graph_config_id  `
+				for _, updateItem := range updateList {
+					updateSQL += `WHEN ` + strconv.Itoa(updateItem.MultipleGraphConfigId) + ` THEN '` + updateItem.Curve + `' `
+				}
+				updateSQL += `END, modify_time = ? WHERE multiple_graph_config_id IN (` + numStr + `)`
+				_, err = to.Raw(updateSQL, time.Now(), configIds).Exec()
+				if err != nil {
+					errmsg = "更新指标A关联图表配置信息失败:Err:" + err.Error()
+					return
+				}
+				logMsg += `涉及到的配置id:` + strings.Join(configIdStr, ",") + ";"
+				replaceConfigTotal += len(configIds)
+				configIds = make([]int, 0)
+				updateList = make([]*MultipleGraphConfig, 0)
+				configIdStr = make([]string, 0)
+			}
+		}
+		if len(configIds) > 0 {
+			numStr := utils.GetOrmInReplace(len(configIds))
+			// 准备批量更新的 SQL 语句
+			updateSQL := `UPDATE multiple_graph_config SET   
+    curve = CASE multiple_graph_config_id  `
+			for _, updateItem := range updateList {
+				updateSQL += `WHEN ` + strconv.Itoa(updateItem.MultipleGraphConfigId) + ` THEN '` + updateItem.Curve + `' `
+			}
+			updateSQL += `END, modify_time = ? WHERE multiple_graph_config_id IN (` + numStr + `)`
+			_, err = to.Raw(updateSQL, time.Now(), configIds).Exec()
+			if err != nil {
+				errmsg = "更新指标A关联图表配置信息失败:Err:" + err.Error()
+				return
+			}
+			logMsg += `涉及到的配置id:` + strings.Join(configIdStr, ",") + ";"
+			replaceConfigTotal += len(configIds)
+			configIds = make([]int, 0)
+			updateList = make([]*MultipleGraphConfig, 0)
+			configIdStr = make([]string, 0)
+		}
+	}
+	return
+}

+ 136 - 0
models/data_manage/multiple_graph_config_chart_mapping.go

@@ -1,7 +1,12 @@
 package data_manage
 
 import (
+	"eta/eta_api/services/alarm_msg"
+	"eta/eta_api/utils"
+	"fmt"
 	"github.com/beego/beego/v2/client/orm"
+	"strconv"
+	"strings"
 	"time"
 )
 
@@ -60,3 +65,134 @@ func GetMultipleGraphConfigChartMappingListById(configId int) (items []*Multiple
 
 	return
 }
+
+// ReplaceMultipleGraphConfigChartEdb 替换相关性分析配置中的指标
+func ReplaceMultipleGraphConfigChartEdb(oldEdbInfo, newEdbInfo *EdbInfo) (replaceConfigTotal int, err error) {
+	var errmsg string
+	logMsg := `` // 记录替换的日志
+
+	o := orm.NewOrmUsingDB("data")
+	to, err := o.Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = to.Rollback()
+		} else {
+			_ = to.Commit()
+			if logMsg != `` {
+				utils.FileLog.Info(fmt.Sprintf("替换相关性分析中的指标记录 替换总数%d,旧的指标id:%d,新的指标id:%d;%s", replaceConfigTotal, oldEdbInfo.EdbInfoId, newEdbInfo.EdbInfoId, logMsg))
+			}
+		}
+		if errmsg != "" {
+			fmt.Println("errmsg:" + errmsg)
+		}
+		if err != nil && errmsg != "" {
+			go alarm_msg.SendAlarmMsg("替换统计分析配置中的指标记录失败提醒,errmsg:"+errmsg, 3)
+		}
+	}()
+	//替换multiple_graph_config中的指标
+	multipleGraphConfigList := make([]*MultipleGraphConfig, 0)
+	csql := `SELECT * FROM multiple_graph_config WHERE (edb_info_id_a=? or edb_info_id_b=?)`
+	_, err = to.Raw(csql, oldEdbInfo.EdbInfoId, oldEdbInfo.EdbInfoId).QueryRows(&multipleGraphConfigList)
+	if err != nil {
+		errmsg = "获取指标关联图表配置信息失败:Err:" + err.Error()
+		return
+	}
+	if len(multipleGraphConfigList) > 0 {
+		replaceConfigTotal = len(multipleGraphConfigList)
+		configIdMap := make(map[int]int)
+		configIds := make([]int, 0)
+		configIdStr := make([]string, 0)
+		for _, mv := range multipleGraphConfigList {
+			if _, ok := configIdMap[mv.MultipleGraphConfigId]; !ok {
+				//判断如果达到1000个数,则执行更新语句
+				configIds = append(configIds, mv.MultipleGraphConfigId)
+				configIdStr = append(configIdStr, strconv.Itoa(mv.MultipleGraphConfigId))
+				configIdMap[mv.MultipleGraphConfigId] = mv.MultipleGraphConfigId
+				if len(configIds) >= 1000 {
+					numStr := utils.GetOrmInReplace(len(configIds))
+					//更新配置中的指标A
+					sql := `UPDATE multiple_graph_config SET edb_info_id_a=?, modify_time=? WHERE edb_info_id_a=? and multiple_graph_config_id IN (` + numStr + `)`
+					_, err = to.Raw(sql, newEdbInfo.EdbInfoId, time.Now(), oldEdbInfo.EdbInfoId, configIds).Exec()
+					if err != nil {
+						errmsg = "更新指标A关联图表配置信息失败:Err:" + err.Error()
+						return
+					}
+					//更新配置中的指标B
+					sql = `UPDATE multiple_graph_config SET edb_info_id_b=?, modify_time=? WHERE edb_info_id_b=? and multiple_graph_config_id IN (` + numStr + `)`
+					_, err = to.Raw(sql, newEdbInfo.EdbInfoId, time.Now(), oldEdbInfo.EdbInfoId, configIds).Exec()
+					if err != nil {
+						errmsg = "更新指标B关联图表配置信息失败:Err:" + err.Error()
+						return
+					}
+
+					// 更新
+					// 更新指标id
+					sql = `UPDATE multiple_graph_config_edb_mapping SET edb_info_id=?, modify_time=? WHERE edb_info_id=? and multiple_graph_config_id IN (` + numStr + `)`
+					_, err = to.Raw(sql, newEdbInfo.EdbInfoId, time.Now(), oldEdbInfo.EdbInfoId, configIds).Exec()
+					if err != nil {
+						errmsg = "更新指标id关联图表配置信息失败:Err:" + err.Error()
+						return
+					}
+					logMsg += `涉及到的配置id:` + strings.Join(configIdStr, ",") + ";"
+					configIds = make([]int, 0)
+					configIdStr = make([]string, 0)
+				}
+			}
+		}
+		if len(configIds) > 0 {
+			numStr := utils.GetOrmInReplace(len(configIds))
+			//更新配置中的指标A
+			sql := `UPDATE multiple_graph_config SET edb_info_id_a=?, modify_time=? WHERE edb_info_id_a=? and multiple_graph_config_id IN (` + numStr + `)`
+			_, err = to.Raw(sql, newEdbInfo.EdbInfoId, time.Now(), oldEdbInfo.EdbInfoId, configIds).Exec()
+			if err != nil {
+				errmsg = "更新指标A关联图表配置信息失败:Err:" + err.Error()
+				return
+			}
+			//更新配置中的指标B
+			sql = `UPDATE multiple_graph_config SET edb_info_id_b=?, modify_time=? WHERE edb_info_id_b=? and multiple_graph_config_id IN (` + numStr + `)`
+			_, err = to.Raw(sql, newEdbInfo.EdbInfoId, time.Now(), oldEdbInfo.EdbInfoId, configIds).Exec()
+			if err != nil {
+				errmsg = "更新指标B关联图表配置信息失败:Err:" + err.Error()
+				return
+			}
+			// 更新指标id
+			sql = `UPDATE multiple_graph_config_edb_mapping SET edb_info_id=?, modify_time=? WHERE edb_info_id=? and multiple_graph_config_id IN (` + numStr + `)`
+			_, err = to.Raw(sql, newEdbInfo.EdbInfoId, time.Now(), oldEdbInfo.EdbInfoId, configIds).Exec()
+			if err != nil {
+				errmsg = "更新指标id关联图表配置信息失败:Err:" + err.Error()
+				return
+			}
+
+			logMsg += `涉及到的配置id:` + strings.Join(configIdStr, ",") + ";"
+			configIds = make([]int, 0)
+			configIdStr = make([]string, 0)
+		}
+	}
+
+	// 更新相关性图表中的
+	sql := `UPDATE chart_info_correlation SET edb_info_id_first=?, modify_time=? WHERE edb_info_id_first=?`
+	_, err = to.Raw(sql, newEdbInfo.EdbInfoId, time.Now(), oldEdbInfo.EdbInfoId).Exec()
+	if err != nil {
+		errmsg = "更新相关性图表中的指标id关联失败:Err:" + err.Error()
+		return
+	}
+	sql = `UPDATE chart_info_correlation SET edb_info_id_second=?, modify_time=? WHERE edb_info_id_second=?`
+	_, err = to.Raw(sql, newEdbInfo.EdbInfoId, time.Now(), oldEdbInfo.EdbInfoId).Exec()
+	if err != nil {
+		errmsg = "更新相关性图表中的指标id关联失败:Err:" + err.Error()
+		return
+	}
+
+	// 替换拟合方程曲线替换指标
+	// 替换跨品种标签绑定得到指标ID
+	sql = `UPDATE chart_tag_variety SET edb_info_id=?, modify_time=? WHERE edb_info_id=?`
+	_, err = to.Raw(sql, newEdbInfo.EdbInfoId, time.Now(), oldEdbInfo.EdbInfoId).Exec()
+	if err != nil {
+		errmsg = "更新指标id关联跨品种分析标签失败:Err:" + err.Error()
+		return
+	}
+	return
+}

+ 2 - 2
models/data_manage/my_chart.go

@@ -870,7 +870,7 @@ func GetMyChartListGroupByCharyInfoIdAndAdminIdByCondition(condition string, par
 func GetRelationChartListByCondition(condition string, pars []interface{}, startSize, pageSize int) (item []*ChartInfoView, err error) {
 	o := orm.NewOrmUsingDB("data")
 	sql := ` SELECT a.* FROM chart_info AS a 
-	JOIN chart_edb_mapping AS b on a.chart_info_id = b.chart_info_id WHERE 1=1 `
+	WHERE 1=1 `
 	if condition != "" {
 		sql += condition
 	}
@@ -883,7 +883,7 @@ func GetRelationChartListByCondition(condition string, pars []interface{}, start
 func GetRelationChartListCountByCondition(condition string, pars []interface{}) (count int, err error) {
 	o := orm.NewOrmUsingDB("data")
 	sql := ` SELECT COUNT(1) AS count FROM chart_info AS a 
-	JOIN chart_edb_mapping AS b on a.chart_info_id = b.chart_info_id WHERE 1=1 `
+	WHERE 1=1 `
 	if condition != "" {
 		sql += condition
 	}

+ 14 - 13
models/permission.go

@@ -10,12 +10,13 @@ type ChartPermissionSearchKeyWordMapping struct {
 	From               string `description:"类型标识" json:"-"`
 	TacticType         string `description:"策略表type字段值" json:"-"`
 	TeleconferenceSort int    `description:"电话会类型排序" json:"-"`
+	ClassifyId         int    `description:"分类ID"`
 }
 
-func GetPermission(classifyNameSecond string) (items []*ChartPermissionSearchKeyWordMapping, err error) {
+func GetPermission(classifyId int) (items []*ChartPermissionSearchKeyWordMapping, err error) {
 	o := orm.NewOrmUsingDB("rddp")
-	sql := `SELECT * FROM chart_permission_search_key_word_mapping AS a WHERE a.from='rddp' AND a.key_word=? `
-	_, err = o.Raw(sql, classifyNameSecond).QueryRows(&items)
+	sql := `SELECT * FROM chart_permission_search_key_word_mapping AS a WHERE a.from='rddp' AND a.classify_id = ? `
+	_, err = o.Raw(sql, classifyId).QueryRows(&items)
 	return
 }
 
@@ -27,7 +28,7 @@ func GetAllPermissionMapping() (items []*ChartPermissionSearchKeyWordMapping, er
 }
 
 // EditChartPermissionSearchKeyWordMappingMulti 修改报告报告权限(先删除原有的权限,再添加新的权限)
-func EditChartPermissionSearchKeyWordMappingMulti(keyword string, permissionIdList []int) (err error) {
+func EditChartPermissionSearchKeyWordMappingMulti(keyword string, permissionIdList []int, classifyId int) (err error) {
 	o := orm.NewOrmUsingDB("rddp")
 	to, err := o.Begin()
 	if err != nil {
@@ -40,8 +41,8 @@ func EditChartPermissionSearchKeyWordMappingMulti(keyword string, permissionIdLi
 			_ = to.Commit()
 		}
 	}()
-	sql := "delete from chart_permission_search_key_word_mapping WHERE `from`='rddp' AND key_word=? "
-	_, err = to.Raw(sql, keyword).Exec()
+	sql := "DELETE FROM chart_permission_search_key_word_mapping WHERE `from` = 'rddp' AND classify_id = ?"
+	_, err = to.Raw(sql, classifyId).Exec()
 	if err != nil {
 		return
 	}
@@ -55,6 +56,7 @@ func EditChartPermissionSearchKeyWordMappingMulti(keyword string, permissionIdLi
 				From:               "rddp",
 				TacticType:         "",
 				TeleconferenceSort: 0,
+				ClassifyId:         classifyId,
 			}
 			chartPermissionSearchKeyWordMappingList = append(chartPermissionSearchKeyWordMappingList, tmpChartPermissionSearchKeyWordMapping)
 		}
@@ -83,18 +85,17 @@ type ChartPermissionMappingIdName struct {
 	PermissionName string
 }
 
-func GetChartPermissionNameFromMappingByKeyword(keyword string, source string) (list []*ChartPermissionMappingIdName, err error) {
+func GetChartPermissionNameFromMappingByKeyword(source string, classifyId int) (list []*ChartPermissionMappingIdName, err error) {
 	o := orm.NewOrmUsingDB("rddp")
-	sql := " SELECT b.chart_permission_id AS permission_id,b.permission_name FROM chart_permission_search_key_word_mapping AS a INNER JOIN chart_permission AS b ON a.chart_permission_id = b.chart_permission_id WHERE a.`from` = ? AND a.key_word = ? "
-	_, err = o.Raw(sql, source, keyword).QueryRows(&list)
-
+	sql := " SELECT b.chart_permission_id AS permission_id,b.permission_name FROM chart_permission_search_key_word_mapping AS a INNER JOIN chart_permission AS b ON a.chart_permission_id = b.chart_permission_id WHERE a.`from` = ? AND a.classify_id = ? "
+	_, err = o.Raw(sql, source, classifyId).QueryRows(&list)
 	return
 }
 
 // UpdateChartPermissionNameFromMappingByKeyword 根据关键词及来源更新新关键词
-func UpdateChartPermissionNameFromMappingByKeyword(newKeyword, keyword, source string) (err error) {
+func UpdateChartPermissionNameFromMappingByKeyword(newKeyword string, classifyId int, source string) (err error) {
 	o := orm.NewOrmUsingDB("rddp")
-	sql := " UPDATE chart_permission_search_key_word_mapping SET key_word = ? WHERE key_word = ? AND `from` = ? "
-	_, err = o.Raw(sql, newKeyword, keyword, source).Exec()
+	sql := " UPDATE chart_permission_search_key_word_mapping SET key_word = ? WHERE classify_id = ? AND `from` = ? "
+	_, err = o.Raw(sql, newKeyword, classifyId, source).Exec()
 	return
 }

+ 8 - 0
models/ppt_english/ppt_english_group_mapping.go

@@ -78,6 +78,14 @@ func GetPptMappingByGroupPptId(groupPptId int64, adminId int) (item *PptEnglishG
 	return
 }
 
+// GetPptMappingByGroupPptId 查询根据映射ID,查询单个映射关系数量
+func GetPptMappingCountByGroupPptId(groupPptId int64, adminId int) (count int, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := `select COUNT(*) AS count from ppt_english_group_mapping where group_ppt_id=? and admin_id=?`
+	err = o.Raw(sql, groupPptId, adminId).QueryRow(&count)
+	return
+}
+
 // Update 更新ppt目录映射的基本信息
 func (item *PptEnglishGroupMapping) Update(cols []string) (err error) {
 	o := orm.NewOrmUsingDB("rddp")

+ 8 - 0
models/ppt_v2_group_mapping.go

@@ -62,6 +62,14 @@ func GetPptMappingByGroupPptId(groupPptId int64, adminId int) (item *PptV2GroupM
 	return
 }
 
+// GetPptMappingByGroupPptId 查询根据映射ID,查询单个映射关系数量
+func GetPptMappingByGroupPptCountId(groupPptId int64, adminId int) (count int, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := `select COUNT(*) AS count from ppt_v2_group_mapping where group_ppt_id=? and admin_id=?`
+	err = o.Raw(sql, groupPptId, adminId).QueryRow(&count)
+	return
+}
+
 // GetPptMappingByPptId 查询根据ppt_Id, 查询当映单个映射关系
 func GetPptMappingByPptId(pptId int64) (item *PptV2GroupMapping, err error) {
 	o := orm.NewOrmUsingDB("rddp")

+ 2 - 2
models/report.go

@@ -230,12 +230,12 @@ func GetReportByIds(reportIds string) (list []*ReportDetail, err error) {
 }
 
 // GetSimpleReportByIds 根据报告ID查询报告基本信息
-func GetSimpleReportByIds(reportIds []int) (list []*ReportDetail, err error) {
+func GetSimpleReportByIds(reportIds []int) (list []*Report, err error) {
 	if len(reportIds) == 0 {
 		return
 	}
 	o := orm.NewOrmUsingDB("rddp")
-	sql := `SELECT id, title FROM report WHERE id IN (` + utils.GetOrmInReplace(len(reportIds)) + `)`
+	sql := `SELECT id, title, report_code FROM report WHERE id IN (` + utils.GetOrmInReplace(len(reportIds)) + `)`
 	_, err = o.Raw(sql, reportIds).QueryRows(&list)
 	return
 }

+ 26 - 0
models/sandbox/sandbox.go

@@ -430,3 +430,29 @@ type DetailParams struct {
 	Id         int    `json:"id"`
 	ClassifyId int    `json:"classifyId"`
 }
+
+// UpdateSandboxContent 更新沙盘内容
+func UpdateSandboxContent(list []Sandbox) (err error) {
+	o := orm.NewOrmUsingDB("data")
+	to, err := o.Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = to.Rollback()
+		} else {
+			_ = to.Commit()
+		}
+	}()
+
+	//循环更新沙盘内容
+	for _, sandbox := range list {
+		_, err = to.Update(&sandbox, "Content", "ModifyTime")
+		if err != nil {
+			return
+		}
+	}
+
+	return
+}

+ 12 - 5
models/sandbox/sandbox_classify.go

@@ -247,10 +247,17 @@ type SandboxLinkCheckReq struct {
 	ReportIdList    []int `description:"报告id列表"`
 }
 
+type SandboxLinkCheckItem struct {
+	Id         int    `description:"id"`
+	Name       string `description:"名称"`
+	UniqueCode string `description:"唯一编码"`
+	ClassifyId int    `description:"分类id"`
+}
+
 type SandboxLinkCheckResp struct {
-	EdbInfoIdList   []int `description:"指标id列表"`
-	ChartInfoIdList []int `description:"图库id列表"`
-	ReportIdList    []int `description:"报告id列表"`
+	EdbInfoIdList   []*SandboxLinkCheckItem `description:"指标id列表"`
+	ChartInfoIdList []*SandboxLinkCheckItem `description:"图库id列表"`
+	ReportIdList    []*SandboxLinkCheckItem `description:"报告id列表"`
 }
 
 // 获取所有子级分类id
@@ -272,7 +279,7 @@ WHERE sc.parent_id = @pv
 // UpdateSandboxClassifyChartPermissionById 根据沙盘id更新品种
 func UpdateSandboxClassifyChartPermissionById(ChartPermissionId int, ChartPermissionName, Ids string) (err error) {
 	o := orm.NewOrmUsingDB("data")
-	sql := ` UPDATE sandbox_classify SET chart_permission_id = ?, chart_permission_name = ? WHERE sandbox_classify_id IN ( `+Ids +` ) `
+	sql := ` UPDATE sandbox_classify SET chart_permission_id = ?, chart_permission_name = ? WHERE sandbox_classify_id IN ( ` + Ids + ` ) `
 	_, err = o.Raw(sql, ChartPermissionId, ChartPermissionName).Exec()
 	return
-}
+}

+ 63 - 0
routers/commentsRouter.go

@@ -3175,6 +3175,69 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:EdbInfoController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:EdbInfoController"],
+        beego.ControllerComments{
+            Method: "CCFClassify",
+            Router: `/ccf/classify`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:EdbInfoController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:EdbInfoController"],
+        beego.ControllerComments{
+            Method: "ExportCCFList",
+            Router: `/ccf/export`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:EdbInfoController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:EdbInfoController"],
+        beego.ControllerComments{
+            Method: "CCFIndexData",
+            Router: `/ccf/index/data`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:EdbInfoController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:EdbInfoController"],
+        beego.ControllerComments{
+            Method: "CCFSearchList",
+            Router: `/ccf/search_list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:EdbInfoController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:EdbInfoController"],
+        beego.ControllerComments{
+            Method: "CCFSingleData",
+            Router: `/ccf/single_data`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:EdbInfoController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:EdbInfoController"],
+        beego.ControllerComments{
+            Method: "CCFStockClassify",
+            Router: `/ccf/stock/classify`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:EdbInfoController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:EdbInfoController"],
+        beego.ControllerComments{
+            Method: "CCFStockTable",
+            Router: `/ccf/stock/table`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:EdbInfoController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:EdbInfoController"],
         beego.ControllerComments{
             Method: "BatchChartInfoRefresh",

+ 10 - 8
services/chart_permission_sync.go

@@ -96,11 +96,12 @@ func ChartFiccPermissionSync() (err error, errMsg string) {
 }
 
 type EditClassifyPermissionReq struct {
-	Keyword string
+	Keyword    string
+	ClassifyId int
 }
 
 // EditClassifyChartPermissionSync 设置报告分类权限
-func EditClassifyChartPermissionSync(keyword string) (err error) {
+func EditClassifyChartPermissionSync(keyword string, classifyId int) (err error) {
 	defer func() {
 		if err != nil {
 			utils.FileLog.Info("同步设置报告分类权限失败, Err: " + err.Error())
@@ -110,7 +111,7 @@ func EditClassifyChartPermissionSync(keyword string) (err error) {
 	if utils.CrmEtaServerUrl == "" {
 		return
 	}
-	req := &EditClassifyPermissionReq{Keyword: keyword}
+	req := &EditClassifyPermissionReq{Keyword: keyword, ClassifyId: classifyId}
 	url := fmt.Sprint(utils.CrmEtaServerUrl, "/api/crm/chart_permission/classify/sync")
 	b, err := crmEtaPost(url, req)
 	if err != nil {
@@ -134,10 +135,11 @@ func EditClassifyChartPermissionSync(keyword string) (err error) {
 type EditReportPermissionSyncReq struct {
 	ReportId           int64  `description:"报告id"`
 	ClassifyNameSecond string `description:"二级分类名称"`
+	ClassifyIdSecond   int    `description:"二级分类ID"`
 }
 
 // EditReportPermissionSync 设置报告权限
-func EditReportPermissionSync(reportId int64, classifyNameSecond string) (err error) {
+func EditReportPermissionSync(reportId int64, classifyIdSecond int) (err error) {
 	defer func() {
 		if err != nil {
 			utils.FileLog.Info("同步设置报告权限失败, Err: " + err.Error())
@@ -147,7 +149,7 @@ func EditReportPermissionSync(reportId int64, classifyNameSecond string) (err er
 	if utils.CrmEtaServerUrl == "" {
 		return
 	}
-	req := &EditReportPermissionSyncReq{ReportId: reportId, ClassifyNameSecond: classifyNameSecond}
+	req := &EditReportPermissionSyncReq{ReportId: reportId, ClassifyIdSecond: classifyIdSecond}
 	url := fmt.Sprint(utils.CrmEtaServerUrl, "/api/crm/chart_permission/report/sync")
 	b, err := crmEtaPost(url, req)
 	if err != nil {
@@ -170,11 +172,11 @@ func EditReportPermissionSync(reportId int64, classifyNameSecond string) (err er
 
 type EditKeywordPermissionSyncReq struct {
 	NewKeyword string
-	Keyword    string
+	ClassifyId int
 }
 
 // EditKeywordPermissionSync 设置报告权限分类名称
-func EditKeywordPermissionSync(newKeyword, keyword string) (err error) {
+func EditKeywordPermissionSync(newKeyword string, classifyId int) (err error) {
 	defer func() {
 		if err != nil {
 			utils.FileLog.Info("同步设置报告权限分类名称失败, Err: " + err.Error())
@@ -184,7 +186,7 @@ func EditKeywordPermissionSync(newKeyword, keyword string) (err error) {
 	if utils.CrmEtaServerUrl == "" {
 		return
 	}
-	req := &EditKeywordPermissionSyncReq{NewKeyword: newKeyword, Keyword: keyword}
+	req := &EditKeywordPermissionSyncReq{NewKeyword: newKeyword, ClassifyId: classifyId}
 	url := fmt.Sprint(utils.CrmEtaServerUrl, "/api/crm/chart_permission/keyword/sync")
 	b, err := crmEtaPost(url, req)
 	if err != nil {

+ 24 - 9
services/data/chart_info.go

@@ -1350,7 +1350,22 @@ func BatchChartInfoRefreshV2(chartInfoList []*data_manage.ChartInfo, redisKey st
 	if totalEdbInfo > 20 { // 关联指标过多的时候,异步刷新
 		isAsync = true
 		isDeleteCache = false // 不删除缓存
-		go refreshChartEdbInfo(chartInfoList, redisKey, newBaseEdbInfoArr, newBasePredictEdbInfoArr, newCalculateMap, newPredictCalculateMap, calculateArr, predictCalculateArr)
+		//go refreshChartEdbInfo(chartInfoList, redisKey, newBaseEdbInfoArr, newBasePredictEdbInfoArr, newCalculateMap, newPredictCalculateMap, calculateArr, predictCalculateArr)
+
+		// 加入队列刷新
+		var refreshItem EdbQueueRefreshReq
+		refreshItem.RefreshKey = redisKey
+		for _, v := range chartInfoList {
+			key := utils.HZ_CHART_LIB_DETAIL + v.UniqueCode
+			refreshItem.ItemRefreshKeys = append(refreshItem.ItemRefreshKeys, key)
+		}
+		refreshItem.BaseEdbInfoArr = newBaseEdbInfoArr
+		refreshItem.BasePredictEdbInfoArr = newBasePredictEdbInfoArr
+		refreshItem.CalculateMap = newCalculateMap
+		refreshItem.PredictCalculateMap = newPredictCalculateMap
+		refreshItem.CalculateArr = calculateArr
+		refreshItem.PredictCalculateArr = predictCalculateArr
+		go PushEdb2Refresh(refreshItem)
 	} else {
 		err = edbInfoRefreshAll(false, newBaseEdbInfoArr, newBasePredictEdbInfoArr, newCalculateMap, newPredictCalculateMap, calculateArr, predictCalculateArr)
 
@@ -1395,15 +1410,15 @@ func refreshChartEdbInfo(chartInfoList []*data_manage.ChartInfo, redisKey string
 // @author: Roc
 // @datetime 2023-11-30 13:30:26
 // @param source string
-// @param reportId int
-// @param reportChapterId int
+// @param primaryId int
+// @param subId int
 // @return string
-func GetBatchChartRefreshKey(source string, reportId, reportChapterId int) string {
+func GetBatchChartRefreshKey(source string, primaryId, subId int) string {
 	if source == `` {
 		return ``
 	}
 
-	return fmt.Sprint("batch_chart_refresh:", source, ":", reportId, ":", reportChapterId)
+	return fmt.Sprint("batch_chart_refresh:", source, ":", primaryId, ":", subId)
 }
 
 // CheckBatchChartRefreshResult
@@ -1411,12 +1426,12 @@ func GetBatchChartRefreshKey(source string, reportId, reportChapterId int) strin
 // @author: Roc
 // @datetime 2023-11-30 13:30:26
 // @param source string
-// @param reportId int
-// @param reportChapterId int
+// @param primaryId int
+// @param subId int
 // @return string
-func CheckBatchChartRefreshResult(source string, reportId, reportChapterId int) (refreshResult bool) {
+func CheckBatchChartRefreshResult(source string, primaryId, subId int) (refreshResult bool) {
 	refreshResult = true
-	redisKey := GetBatchChartRefreshKey(source, reportId, reportChapterId)
+	redisKey := GetBatchChartRefreshKey(source, primaryId, subId)
 	if redisKey != `` {
 		// 如果找到了key,那么就是还在更新中
 		isOk := utils.Rc.IsExist(redisKey)

+ 88 - 16
services/data/edb_classify.go

@@ -495,7 +495,7 @@ func EditEdbClassify(classifyId int, classifyName, lang string, sysUser *system.
 }
 
 // DeleteCheck 删除检测
-func DeleteCheck(classifyId, edbInfoId int, sysUser *system.Admin) (deleteStatus int, tipsMsg string, err error, errMsg string) {
+func DeleteCheck(classifyId, edbInfoId int, sysUser *system.Admin) (deleteStatus int, tipsMsg string, tableList []*data_manage.ExcelBaseInfo, err error, errMsg string) {
 	//删除分类
 	if classifyId > 0 && edbInfoId == 0 {
 		// 查找分类
@@ -603,7 +603,7 @@ func DeleteCheck(classifyId, edbInfoId int, sysUser *system.Admin) (deleteStatus
 			}
 			if calculateCount > 0 {
 				deleteStatus = 4
-				tipsMsg = "当前指标已用作指标运算,不可删除"
+				tipsMsg = "当前指标已用作指标运算,不可删除"
 				return
 			}
 		}
@@ -617,7 +617,7 @@ func DeleteCheck(classifyId, edbInfoId int, sysUser *system.Admin) (deleteStatus
 				return
 			}
 			if predictEdbInfoCount > 0 {
-				deleteStatus = 3
+				deleteStatus = 5
 				tipsMsg = "当前指标已用作预测指标,不可删除"
 				return
 			}
@@ -625,22 +625,66 @@ func DeleteCheck(classifyId, edbInfoId int, sysUser *system.Admin) (deleteStatus
 
 		// 判断指标是否用作表格引用
 		{
-			calculateCount, tmpErr := excel.GetNoCustomAnalysisExcelEdbMappingCount(edbInfoId)
+			tableItems, tmpErr := excel.GetNoCustomAnalysisExcelEdbMapping(edbInfoId)
 			if tmpErr != nil && tmpErr.Error() != utils.ErrNoRow() {
 				errMsg = "删除失败"
 				err = errors.New("判断指标是否用作表格引用,GetNoCustomAnalysisExcelEdbMappingCount Err:" + tmpErr.Error())
 				return
 			}
-			if calculateCount > 0 {
-				deleteStatus = 3
-				tipsMsg = "当前指标已添加到表格,不可删除"
+			//英文翻译:
+			//1、当前指标已用作画图,不可删除:The current metric is in use for charting and cannot be deleted
+			//2、当前指标已被表格引用,不可删除:The current metric is referenced by a table and cannot be deleted
+			//3、删除失败:Deletion failed
+			//4、知道了:Understood
+			if len(tableItems) > 0 {
+				deleteStatus = 6
+				tipsMsg = "当前指标已被表格引用,不可删除"
+				var excelIds []int
+				for _, tableItem := range tableItems {
+					if tableItem.ParentId > 0 {
+						excelIds = append(excelIds, tableItem.ParentId)
+					} else {
+						excelIds = append(excelIds, tableItem.ExcelInfoId)
+					}
+				}
+				tableList, tmpErr = excel.GetExcelBaseInfoByExcelInfoIdList(excelIds)
+				if tmpErr != nil && tmpErr.Error() != utils.ErrNoRow() {
+					errMsg = "删除失败"
+					err = errors.New("判断指标是否用作表格引用,GetExcelBaseInfoByExcelInfoIdList Err:" + tmpErr.Error())
+					return
+				}
 				return
 			}
 		}
 
 		// 判断指标是否用作跨品种图表使用
 		{
-			calculateCount, tmpErr := cross_variety.GetCountByEdbInfoId(edbInfoId)
+			// todo 如果绑定的标签未画图,则允许删除绑定
+			// 查询跨品种的图表
+			tagXList, tmpErr := cross_variety.GetChartInfoCrossVarietyByXEdbInfoId(edbInfoId)
+			if tmpErr != nil && tmpErr.Error() != utils.ErrNoRow() {
+				errMsg = "删除失败"
+				err = errors.New("判断指标是否用作跨品种图表使用,GetChartInfoCrossVarietyByXEdbInfoId Err:" + tmpErr.Error())
+				return
+			}
+			if len(tagXList) > 0 {
+				deleteStatus = 7
+				tipsMsg = "当前指标已添加到跨品种分析,不可删除"
+				return
+			}
+			tagYList, tmpErr := cross_variety.GetChartInfoCrossVarietyByYEdbInfoId(edbInfoId)
+			if tmpErr != nil && tmpErr.Error() != utils.ErrNoRow() {
+				errMsg = "删除失败"
+				err = errors.New("判断指标是否用作跨品种图表使用,GetChartInfoCrossVarietyByYEdbInfoId Err:" + tmpErr.Error())
+				return
+			}
+
+			if len(tagYList) > 0 {
+				deleteStatus = 7
+				tipsMsg = "当前指标已添加到跨品种分析,不可删除"
+				return
+			}
+			/*calculateCount, tmpErr := cross_variety.GetCountByEdbInfoId(edbInfoId)
 			if tmpErr != nil && tmpErr.Error() != utils.ErrNoRow() {
 				errMsg = "删除失败"
 				err = errors.New("判断指标是否用作跨品种图表使用,GetCountByEdbInfoId Err:" + tmpErr.Error())
@@ -650,14 +694,14 @@ func DeleteCheck(classifyId, edbInfoId int, sysUser *system.Admin) (deleteStatus
 				deleteStatus = 3
 				tipsMsg = "当前指标已添加到跨品种分析,不可删除"
 				return
-			}
+			}*/
 		}
 	}
 	return
 }
 
 // Delete 删除分类/指标
-func Delete(classifyId, edbInfoId int, sysUser *system.Admin, requestBody, requestUrl string) (nextItem *data_manage.EdbInfo, err error, errMsg string) {
+func Delete(classifyId, edbInfoId int, sysUser *system.Admin, requestBody, requestUrl string) (nextItem *data_manage.EdbInfo, tableList []*data_manage.ExcelBaseInfo, err error, errMsg string) {
 	//删除分类
 	if classifyId > 0 && edbInfoId == 0 {
 		// 查找分类
@@ -779,21 +823,49 @@ func Delete(classifyId, edbInfoId int, sysUser *system.Admin, requestBody, reque
 
 		// 判断指标是否用作表格引用
 		{
-			calculateCount, tmpErr := excel.GetNoCustomAnalysisExcelEdbMappingCount(edbInfoId)
+			tableItems, tmpErr := excel.GetNoCustomAnalysisExcelEdbMapping(edbInfoId)
 			if tmpErr != nil && tmpErr.Error() != utils.ErrNoRow() {
 				errMsg = "删除失败"
 				err = errors.New("判断指标是否用作表格引用,GetNoCustomAnalysisExcelEdbMappingCount Err:" + tmpErr.Error())
 				return
 			}
-			if calculateCount > 0 {
-				errMsg = "当前指标已添加到表格,不可删除"
+			//英文翻译:
+			//1、当前指标已用作画图,不可删除:The current metric is in use for charting and cannot be deleted
+			//2、当前指标已被表格引用,不可删除:The current metric is referenced by a table and cannot be deleted
+			//3、删除失败:Deletion failed
+			//4、知道了:Understood
+			if len(tableItems) > 0 {
+				errMsg = "当前指标已被表格引用,不可删除"
 				return
 			}
 		}
-
 		// 判断指标是否用作跨品种图表使用
 		{
-			calculateCount, tmpErr := cross_variety.GetCountByEdbInfoId(edbInfoId)
+			// todo 如果绑定的标签未画图,则允许删除绑定
+			// 查询跨品种的图表
+			tagXList, tmpErr := cross_variety.GetChartInfoCrossVarietyByXEdbInfoId(edbInfoId)
+			if tmpErr != nil && tmpErr.Error() != utils.ErrNoRow() {
+				errMsg = "删除失败"
+				err = errors.New("判断指标是否用作跨品种图表使用,GetChartInfoCrossVarietyByXEdbInfoId Err:" + tmpErr.Error())
+				return
+			}
+			if len(tagXList) > 0 {
+				errMsg = "当前指标已添加到跨品种分析,不可删除"
+				return
+			}
+			tagYList, tmpErr := cross_variety.GetChartInfoCrossVarietyByYEdbInfoId(edbInfoId)
+			if tmpErr != nil && tmpErr.Error() != utils.ErrNoRow() {
+				errMsg = "删除失败"
+				err = errors.New("判断指标是否用作跨品种图表使用,GetChartInfoCrossVarietyByYEdbInfoId Err:" + tmpErr.Error())
+				return
+			}
+
+			if len(tagYList) > 0 {
+				errMsg = "当前指标已添加到跨品种分析,不可删除"
+				return
+			}
+
+			/*calculateCount, tmpErr := cross_variety.GetCountByEdbInfoId(edbInfoId)
 			if tmpErr != nil && tmpErr.Error() != utils.ErrNoRow() {
 				errMsg = "删除失败"
 				err = errors.New("判断指标是否用作跨品种图表使用,GetCountByEdbInfoId Err:" + tmpErr.Error())
@@ -802,7 +874,7 @@ func Delete(classifyId, edbInfoId int, sysUser *system.Admin, requestBody, reque
 			if calculateCount > 0 {
 				errMsg = "当前指标已添加到跨品种分析,不可删除"
 				return
-			}
+			}*/
 		}
 
 		//真实删除

+ 30 - 18
services/data/edb_info.go

@@ -2619,24 +2619,36 @@ func BatchRefreshEdbByEdbIds(edbIdList []int, redisKey string, refreshKeys []str
 	if totalEdbInfo > 20 {
 		syncing = true
 
-		go func() {
-			defer func() {
-				if err != nil {
-					alarm_msg.SendAlarmMsg("BatchRefreshEdbByEdbIds, ErrMsg: "+err.Error(), 3)
-				}
-			}()
-
-			err = edbInfoRefreshAll(false, newBaseEdbInfoArr, newBasePredictEdbInfoArr, newCalculateMap, newPredictCalculateMap, calculateArr, predictCalculateArr)
-
-			if redisKey != `` {
-				_ = utils.Rc.Delete(redisKey)
-			}
-			if len(refreshKeys) > 0 {
-				for _, v := range refreshKeys {
-					_ = utils.Rc.Delete(v)
-				}
-			}
-		}()
+		//go func() {
+		//	defer func() {
+		//		if err != nil {
+		//			alarm_msg.SendAlarmMsg("BatchRefreshEdbByEdbIds, ErrMsg: "+err.Error(), 3)
+		//		}
+		//	}()
+		//
+		//	err = edbInfoRefreshAll(false, newBaseEdbInfoArr, newBasePredictEdbInfoArr, newCalculateMap, newPredictCalculateMap, calculateArr, predictCalculateArr)
+		//
+		//	if redisKey != `` {
+		//		_ = utils.Rc.Delete(redisKey)
+		//	}
+		//	if len(refreshKeys) > 0 {
+		//		for _, v := range refreshKeys {
+		//			_ = utils.Rc.Delete(v)
+		//		}
+		//	}
+		//}()
+
+		// 加入队列刷新
+		var refreshItem EdbQueueRefreshReq
+		refreshItem.RefreshKey = redisKey
+		refreshItem.ItemRefreshKeys = refreshKeys
+		refreshItem.BaseEdbInfoArr = newBaseEdbInfoArr
+		refreshItem.BasePredictEdbInfoArr = newBasePredictEdbInfoArr
+		refreshItem.CalculateMap = newCalculateMap
+		refreshItem.PredictCalculateMap = newPredictCalculateMap
+		refreshItem.CalculateArr = calculateArr
+		refreshItem.PredictCalculateArr = predictCalculateArr
+		go PushEdb2Refresh(refreshItem)
 		return
 	}
 

+ 105 - 0
services/data/edb_refresh.go

@@ -0,0 +1,105 @@
+package data
+
+import (
+	"eta/eta_api/models/data_manage"
+	"eta/eta_api/services/alarm_msg"
+	"eta/eta_api/utils"
+	"fmt"
+	"sync"
+)
+
+var (
+	EdbRefreshLock     sync.Map                // 指标刷新锁, 避免同时间重复key的刷新
+	EdbRefreshHandling chan EdbQueueRefreshReq // 排队刷新的20+指标的图表/表格
+	EdbRefreshWorker   chan struct{}           // 同时允许N组刷新
+)
+
+func init() {
+	EdbRefreshHandling = make(chan EdbQueueRefreshReq, 50) // N为最大排队等候的goroutine数
+	EdbRefreshWorker = make(chan struct{}, 5)              // 控制刷新速率修改此N值
+}
+
+type EdbQueueRefreshReq struct {
+	RefreshKey            string   `description:"刷新请求的缓存key"`
+	ItemRefreshKeys       []string `description:"图表/表格刷新后要删除的缓存key"`
+	BaseEdbInfoArr        []*data_manage.EdbInfo
+	BasePredictEdbInfoArr []*data_manage.EdbInfo
+	CalculateMap          map[int]*data_manage.EdbInfo
+	PredictCalculateMap   map[int]*data_manage.EdbInfo
+	CalculateArr          []int
+	PredictCalculateArr   []int
+}
+
+// PushEdb2Refresh 写入指标刷新队列
+func PushEdb2Refresh(item EdbQueueRefreshReq) {
+	refreshKey := item.RefreshKey
+	if refreshKey == "" {
+		return
+	}
+
+	// 检查是否已在队列中
+	_, ok := EdbRefreshLock.Load(refreshKey)
+	if ok {
+		return
+	}
+
+	// 追加至刷新队列
+	EdbRefreshHandling <- item
+
+	EdbRefreshLock.Store(refreshKey, true)
+}
+
+// HandleEdbRefreshQueue 排队刷新指标
+func HandleEdbRefreshQueue() {
+	defer func() {
+		if err := recover(); err != nil {
+			tips := fmt.Sprintf("[HandleEdbRefreshQueue] panic: %v", err)
+			fmt.Println(tips)
+			utils.FileLog.Info(tips)
+		}
+	}()
+	fmt.Println("HandleEdbRefreshQueue start")
+
+	for {
+		select {
+		case item, ok := <-EdbRefreshHandling:
+			if !ok {
+				return
+			}
+			go EdbRefreshTask(item)
+		}
+	}
+}
+
+// EdbRefreshTask 指标刷新任务
+func EdbRefreshTask(item EdbQueueRefreshReq) {
+	var err error
+	defer func() {
+		if err != nil {
+			tips := fmt.Sprintf("[EdbRefreshTask] ErrMsg: %s", err.Error())
+			utils.FileLog.Info(tips)
+			go alarm_msg.SendAlarmMsg(tips, 3)
+		}
+		<-EdbRefreshWorker
+	}()
+	EdbRefreshWorker <- struct{}{}
+
+	fmt.Printf("EdbRefreshTask开始刷新: %s\n", item.RefreshKey)
+	// 刷新指标
+	e := edbInfoRefreshAll(false, item.BaseEdbInfoArr, item.BasePredictEdbInfoArr, item.CalculateMap, item.PredictCalculateMap, item.CalculateArr, item.PredictCalculateArr)
+	if e != nil {
+		err = fmt.Errorf("edbInfoRefreshAll err: %s", e.Error())
+	}
+
+	// 清除缓存
+	_ = utils.Rc.Delete(item.RefreshKey)
+	if len(item.ItemRefreshKeys) > 0 {
+		for _, v := range item.ItemRefreshKeys {
+			_ = utils.Rc.Delete(v)
+		}
+	}
+
+	// 解除锁
+	EdbRefreshLock.Delete(item.RefreshKey)
+	fmt.Printf("EdbRefreshTask结束刷新: %s\n", item.RefreshKey)
+}

+ 2 - 2
services/data/excel/excel_info.go

@@ -520,10 +520,10 @@ func GetEdbIdsFromExcelCodes(excelCodes []string, sysUserId int, lang string) (e
 }
 
 // GetExcelEdbBatchRefreshKey 获取批量刷新表格指标缓存key
-func GetExcelEdbBatchRefreshKey(source string, reportId, chapterId int) string {
+func GetExcelEdbBatchRefreshKey(source string, primaryId, subId int) string {
 	if source == `` {
 		return ``
 	}
 
-	return fmt.Sprint("batch_refresh_excel_edb:", source, ":", reportId, ":", chapterId)
+	return fmt.Sprint("batch_refresh_excel_edb:", source, ":", primaryId, ":", subId)
 }

+ 254 - 0
services/edb_info_replace.go

@@ -0,0 +1,254 @@
+package services
+
+import (
+	"encoding/json"
+	"errors"
+	"eta/eta_api/models/data_manage"
+	excelModel "eta/eta_api/models/data_manage/excel"
+	"eta/eta_api/models/data_manage/excel/request"
+	"eta/eta_api/services/alarm_msg"
+	"eta/eta_api/services/sandbox"
+	"eta/eta_api/utils"
+	"fmt"
+	"time"
+)
+
+// 全局的指标替换
+func DealReplaceEdbCache() {
+	var err error
+	for {
+		utils.Rc.Brpop(utils.CACHE_KEY_REPLACE_EDB, func(b []byte) {
+			defer func() {
+				if err != nil {
+					utils.FileLog.Info("DealReplaceEdbCache err:" + err.Error())
+					go alarm_msg.SendAlarmMsg("替换表格中的指标失败提醒,errmsg:"+err.Error(), 3)
+				}
+			}()
+			record := new(data_manage.ReplaceEdbInfoItem)
+			if err = json.Unmarshal(b, &record); err != nil {
+				fmt.Println("json unmarshal wrong!")
+				return
+			}
+			oldEdbInfo := record.OldEdbInfo
+			newEdbInfo := record.NewEdbInfo
+			deleteCache := true
+			setNxKey := fmt.Sprintf("EDB_INFO_REPLACE:%d-%d", oldEdbInfo.EdbInfoId, newEdbInfo.EdbInfoId)
+			defer func() {
+				if deleteCache {
+					utils.Rc.Delete(setNxKey)
+				}
+			}()
+			if !utils.Rc.SetNX(setNxKey, 1, 30*time.Minute) {
+				deleteCache = false
+				err = fmt.Errorf("替换表格中的指标失败旧指标:%d为新指标%d:正在处理中", oldEdbInfo.EdbInfoId, newEdbInfo.EdbInfoId)
+				return
+			}
+
+			// 替换相关性图表配置
+			_, err = data_manage.ReplaceMultipleGraphConfigChartEdb(oldEdbInfo, newEdbInfo)
+			if err != nil {
+				err = fmt.Errorf("替换相关性图表配置失败,errmsg:%s", err.Error())
+				return
+			}
+			// 替换拟合方程指标
+			_, err = data_manage.ReplaceEdbInfoInLineEquationMultipleGraphConfig(oldEdbInfo, newEdbInfo)
+			if err != nil {
+				err = fmt.Errorf("替换拟合方程指标失败,errmsg:%s", err.Error())
+				return
+			}
+
+			// 替换表格中的指标
+			err = ReplaceEdbInExcel(oldEdbInfo, newEdbInfo)
+			if err != nil {
+				err = fmt.Errorf("替换表格中的指标失败,errmsg:%s", err.Error())
+				return
+			}
+
+			//替换逻辑图中的指标
+			err = sandbox.ReplaceEdbInSandbox(oldEdbInfo.EdbInfoId, newEdbInfo.EdbInfoId)
+			if err != nil {
+				err = fmt.Errorf("替换逻辑图中的指标失败,errmsg:%s", err.Error())
+				return
+			}
+		})
+	}
+}
+
+// ReplaceEdbInExcel 替换表格中的指标
+func ReplaceEdbInExcel(oldEdbInfo, newEdbInfo *data_manage.EdbInfo) (err error) {
+	defer func() {
+		if err != nil {
+			go alarm_msg.SendAlarmMsg("替换表格中的指标失败提醒,errmsg:"+err.Error(), 3)
+		}
+	}()
+	//查询和指标相关的时间序列表格和混合表格
+	mappingList, err := excelModel.GetExcelEdbMappingByEdbInfoIdAndSource(oldEdbInfo.EdbInfoId, []int{utils.TIME_TABLE, utils.MIXED_TABLE})
+	if err != nil {
+		err = fmt.Errorf("查询和指标相关的表格失败,错误:%s", err.Error())
+		return
+	}
+	updateList := make([]*excelModel.ExcelInfo, 0)
+	// 循环列表,根据表格类型单独处理
+	for _, excelMapping := range mappingList {
+		//查询和指标相关的混合表格
+		excelInfo, tmpErr := excelModel.GetExcelInfoById(excelMapping.ExcelInfoId)
+		if tmpErr != nil {
+			err = fmt.Errorf("查询和指标相关的混合表格失败,错误:%s", tmpErr.Error())
+			return
+		}
+		// 清除缓存
+		key := utils.HZ_CHART_LIB_EXCEL_TABLE_DETAIL + ":" + excelInfo.UniqueCode
+		if utils.Re == nil {
+			_ = utils.Rc.Delete(key)
+		}
+		// 根据表格类型,调用不同的处理函数
+		switch excelMapping.Source {
+		case utils.TIME_TABLE: // 时间序列表格
+			// 替换余额表格中的指标
+			newExcelInfo, e := replaceEdbInTimeExcel(oldEdbInfo, newEdbInfo, excelInfo)
+			if e != nil {
+				err = fmt.Errorf("替换余额表格中的指标失败,错误:%s", e.Error())
+				return
+			}
+			updateList = append(updateList, newExcelInfo)
+		case utils.MIXED_TABLE, utils.BALANCE_TABLE:
+			// 替换余额表格中的指标
+			newExcelInfo, e := replaceEdbInBalanceExcel(oldEdbInfo, newEdbInfo, excelInfo)
+			if e != nil {
+				err = fmt.Errorf("替换余额表格中的指标失败,错误:%s", e.Error())
+				return
+			}
+			updateList = append(updateList, newExcelInfo)
+		default:
+			// 其他表格类型的处理逻辑
+		}
+	}
+
+	err = excelModel.ReplaceEdbInExcel(oldEdbInfo.EdbInfoId, newEdbInfo.EdbInfoId, updateList)
+	if err != nil {
+		err = fmt.Errorf("替换表格中的指标失败,错误:%s", err.Error())
+		return
+	}
+
+	//todo 是否需要刷新表格中的指标数据
+	return
+}
+
+func replaceEdbInBalanceExcel(oldEdbInfo, newEdbInfo *data_manage.EdbInfo, excelInfo *excelModel.ExcelInfo) (newExcelInfo *excelModel.ExcelInfo, err error) {
+	newExcelInfo = excelInfo
+	var mixedTableReq request.MixedTableReq
+	err = json.Unmarshal([]byte(excelInfo.Content), &mixedTableReq)
+	if err != nil {
+		err = fmt.Errorf("表格json转结构体失败,Err:" + err.Error())
+		return
+	}
+	// 处理data
+	configList := mixedTableReq.Data
+	for ck, rowList := range configList {
+		for rk, cell := range rowList {
+			switch cell.DataType {
+			case request.EdbDT: // 指标信息
+				if cell.EdbInfoId == oldEdbInfo.EdbInfoId {
+					//更换成新指标ID
+					configList[ck][rk].EdbInfoId = newEdbInfo.EdbInfoId
+				}
+			case request.InsertDataDT, request.PopInsertDataDT: // 插值、弹框插值
+				if cell.EdbInfoId == oldEdbInfo.EdbInfoId {
+					//更换成新指标ID
+					configList[ck][rk].EdbInfoId = newEdbInfo.EdbInfoId
+				}
+			case request.InsertEdbCalculateDataDT: // 插入指标计算公式生成的值
+				var config request.CalculateConf
+				err = json.Unmarshal([]byte(cell.Value), &config)
+				if err != nil {
+					return
+				}
+				if cell.EdbInfoId == oldEdbInfo.EdbInfoId {
+					//更换成新指标ID
+					configList[ck][rk].EdbInfoId = newEdbInfo.EdbInfoId
+				}
+				if config.EdbInfoId == oldEdbInfo.EdbInfoId {
+					config.EdbInfoId = newEdbInfo.EdbInfoId
+					var configStr []byte
+					configStr, err = json.Marshal(config)
+					if err != nil {
+						return
+					}
+					configList[ck][rk].Value = string(configStr)
+				}
+
+			case request.DateDT: // 日期类型
+				// 指标日期类型的单元格需要额外将指标id取出来
+				if cell.DataTimeType == request.EdbDateDT {
+					var config request.EdbDateConf
+					err = json.Unmarshal([]byte(cell.Value), &config)
+					if err != nil {
+						return
+					}
+					if config.EdbInfoId == oldEdbInfo.EdbInfoId {
+						config.EdbInfoId = newEdbInfo.EdbInfoId
+						var configStr []byte
+						configStr, err = json.Marshal(config)
+						if err != nil {
+							return
+						}
+						configList[ck][rk].Value = string(configStr)
+					}
+				}
+			}
+		}
+	}
+
+	mixedTableReq.Data = configList
+	var newContentByte []byte
+	newContentByte, err = json.Marshal(mixedTableReq)
+	if err != nil {
+		return
+	}
+	// 生成的新内容替换原先的旧内容
+	excelInfo.Content = string(newContentByte)
+	newExcelInfo = excelInfo
+	return
+}
+
+func replaceEdbInTimeExcel(oldEdbInfo, newEdbInfo *data_manage.EdbInfo, excelInfo *excelModel.ExcelInfo) (newExcelInfo *excelModel.ExcelInfo, err error) {
+	newExcelInfo = excelInfo
+
+	var tableDataConfig request.TimeTableDataConfig
+	err = json.Unmarshal([]byte(excelInfo.Content), &tableDataConfig)
+	if err != nil {
+		err = errors.New("表格json转结构体失败,Err:" + err.Error())
+		return
+	}
+	if len(tableDataConfig.EdbInfoIdList) <= 0 {
+		return
+	}
+	// 实际期数没有的情况下,直接返回吧
+	if tableDataConfig.Num <= 0 {
+		return
+	}
+
+	// 先处理edbInfoList
+	for k, id := range tableDataConfig.EdbInfoIdList {
+		if id == oldEdbInfo.EdbInfoId {
+			tableDataConfig.EdbInfoIdList[k] = newEdbInfo.EdbInfoId
+		}
+	}
+
+	// 先处理tableEdbInfoList
+	for k, tableEdbInfo := range tableDataConfig.TableEdbInfoList {
+		if tableEdbInfo.EdbInfoId == oldEdbInfo.EdbInfoId {
+			tableDataConfig.TableEdbInfoList[k].EdbInfoId = newEdbInfo.EdbInfoId
+		}
+	}
+
+	var newContentByte []byte
+	newContentByte, err = json.Marshal(tableDataConfig)
+	if err != nil {
+		return
+	}
+	// 生成的新内容替换原先的旧内容
+	excelInfo.Content = string(newContentByte)
+	newExcelInfo = excelInfo
+	return
+}

+ 3 - 3
services/report.go

@@ -409,7 +409,7 @@ func UpdateReportEs(reportId int, publishState int) (err error) {
 		}
 	} else {
 		//if utils.BusinessCode == utils.BusinessCodeRelease || utils.BusinessCode == utils.BusinessCodeSandbox {
-		permissionList, tmpErr := models.GetChartPermissionNameFromMappingByKeyword(reportInfo.ClassifyNameSecond, "rddp")
+		permissionList, tmpErr := models.GetChartPermissionNameFromMappingByKeyword("rddp", reportInfo.ClassifyIdSecond)
 		if tmpErr != nil {
 			return
 		}
@@ -993,7 +993,7 @@ func CreateNewReport(req models.AddReq, adminInfo *system.Admin) (newReportId in
 	// 处理权限
 	//if utils.BusinessCode == utils.BusinessCodeRelease || utils.BusinessCode == utils.BusinessCodeSandbox {
 	go func() {
-		permissionItems, e := models.GetPermission(req.ClassifyNameSecond)
+		permissionItems, e := models.GetPermission(req.ClassifyIdSecond)
 		if e != nil {
 			alarm_msg.SendAlarmMsg("获取权限失败,Err:"+err.Error(), 3)
 		}
@@ -1004,7 +1004,7 @@ func CreateNewReport(req models.AddReq, adminInfo *system.Admin) (newReportId in
 			}
 		}
 		// 同步crm权限
-		_ = EditReportPermissionSync(newReportId, req.ClassifyNameSecond)
+		_ = EditReportPermissionSync(newReportId, req.ClassifyIdSecond)
 	}()
 	//}
 

+ 3 - 3
services/report_classify.go

@@ -88,8 +88,7 @@ func AfterUpdateClassifyNameOrParent(classifyId, parentId, originParentId int, o
 	// 二级分类-修改名称
 	if originName != classifyName && parentId > 0 {
 		// 更新关键词
-		// todo 更新crm里的权限关键词
-		if e := models.UpdateChartPermissionNameFromMappingByKeyword(classifyName, originName, "rddp"); e != nil {
+		if e := models.UpdateChartPermissionNameFromMappingByKeyword(classifyName, classifyId, "rddp"); e != nil {
 			err = fmt.Errorf("更新二级分类关键词失败, Err: %s", e.Error())
 			return
 		}
@@ -99,7 +98,8 @@ func AfterUpdateClassifyNameOrParent(classifyId, parentId, originParentId int, o
 			return
 		}
 
-		_ = EditKeywordPermissionSync(classifyName, originName)
+		// 同步crm_master
+		_ = EditKeywordPermissionSync(classifyName, classifyId)
 		return
 	}
 

+ 63 - 0
services/sandbox/sandbox.go

@@ -7,9 +7,11 @@ import (
 	"eta/eta_api/models/sandbox"
 	"eta/eta_api/models/sandbox/request"
 	"eta/eta_api/models/system"
+	"eta/eta_api/services/alarm_msg"
 	"eta/eta_api/utils"
 	"fmt"
 	"strconv"
+	"strings"
 	"time"
 )
 
@@ -892,5 +894,66 @@ func GetSandBoxEdbIdsByContent(content string) (edbInfoIds []int, err error) {
 			}
 		}
 	}
+}
+func ReplaceEdbInSandbox(oldEdbInfoId, newEdbInfoId int) (err error) {
+	updateTotal := 0
+	logMsg := ""
+	//分页处理沙盘表
+	defer func() {
+		if err != nil {
+			go alarm_msg.SendAlarmMsg("替换沙盘中的指标记录失败提醒,errmsg:"+err.Error(), 3)
+		}
+		if logMsg != "" {
+			utils.FileLog.Info(fmt.Sprintf("替换ETA逻辑的指标记录,替换总数:%d,旧的指标id:%d,新的指标id:%d;%s", updateTotal, oldEdbInfoId, newEdbInfoId, logMsg))
+		}
+	}()
+	//查询沙盘总数
+	total, err := sandbox.GetSandboxListCountByCondition("", []interface{}{})
+	if err != nil {
+		err = fmt.Errorf("查询沙盘总数失败 Err:%s", err)
+		return
+	}
+
+	// 根据沙盘列表总数,分页查询
+	// 计算总页数
+	totalPage := (total + 99) / 100 // 使用整数除法,并添加一页以防有余数
+	updateSandBox := make([]sandbox.Sandbox, 0)
+
+	//查询沙盘列表
+	for i := 0; i < totalPage; i += 1 {
+		startSize := i * 100
+		list, e := sandbox.GetSandboxListByCondition("", []interface{}{}, startSize, 100)
+		if e != nil {
+			err = fmt.Errorf("查询沙盘列表失败 Err:%s", e)
+			return
+		}
+		for _, v := range list {
+			sandOldEdbId := fmt.Sprintf(`"RId":"1-%d","Id":%d,`, oldEdbInfoId, oldEdbInfoId)
+			if strings.Contains(v.Content, sandOldEdbId) {
+				sandNewEdbId := fmt.Sprintf(`"RId":"1-%d","Id":%d,`, newEdbInfoId, newEdbInfoId)
+				v.Sandbox.Content = strings.ReplaceAll(v.Content, sandOldEdbId, sandNewEdbId)
+				updateSandBox = append(updateSandBox, v.Sandbox)
+				logMsg += `涉及到的逻辑id:` + strconv.Itoa(v.Sandbox.SandboxId) + ";"
+				if len(updateSandBox) > 100 {
+					err = sandbox.UpdateSandboxContent(updateSandBox)
+					if err != nil {
+						err = fmt.Errorf("更新沙盘表失败 Err:%s", err)
+						return
+					}
+					updateTotal += len(updateSandBox)
+					updateSandBox = make([]sandbox.Sandbox, 0)
+				}
+			}
+		}
+	}
+	if len(updateSandBox) > 0 {
+		err = sandbox.UpdateSandboxContent(updateSandBox)
+		if err != nil {
+			err = fmt.Errorf("更新沙盘表失败 Err:%s", err)
+			return
+		}
+		updateTotal += len(updateSandBox)
+	}
+
 	return
 }

+ 5 - 2
services/task.go

@@ -40,8 +40,11 @@ func Task() {
 
 	go AutoInsertAdminOperateRecordToDB()
 
-	// 测试用-生成bloomberg数据
-	//go InsertBloombergIndex()
+	// 指标刷新
+	go data.HandleEdbRefreshQueue()
+
+	// 进行指标替换操作
+	go DealReplaceEdbCache()
 
 	// TODO:修复权限
 	//FixEnCompanyPermission()

+ 8 - 1
static/ErrMsgConfig.json

@@ -50,5 +50,12 @@
   "系统处理中,请稍后重试!": "The system is processing, please try again later!",
   "固定日期不可为空": "The fixed date cannot be empty",
   "日期数量已达上限!": "The number of dates has reached the limit!",
-  "该品种已在指标库生成指标,不可删除": "This variety has already generated indicators in the index library and cannot be deleted"
+  "该品种已在指标库生成指标,不可删除": "This variety has already generated indicators in the index library and cannot be deleted",
+  "当前指标已用作画图,不可删除": "The current metric is in use for charting and cannot be deleted",
+  "当前指标已被表格引用,不可删除":"The current metric is referenced by a table and cannot be deleted",
+  "当前指标已用作指标运算,不可删除": "The current metric is used in metric calculations and cannot be deleted.",
+  "当前指标已用作预测指标,不可删除": "The current metric is used as a forecasting indicator and cannot be deleted.",
+  "当前指标已添加到跨品种分析,不可删除": "The current metric has been added to cross-commodity analysis and cannot be deleted.",
+  "指标已删除,请刷新页面": "Metric deleted, please refresh the page.",
+  "删除失败": "Deletion failed."
 }

+ 2 - 0
utils/constants.go

@@ -232,6 +232,8 @@ const (
 
 	CACHE_CREATE_REPORT_IMGPDF_QUEUE = "eta_report:report_img_pdf_queue" // 生成报告长图PDF队列
 	CACHE_EDB_TERMINAL_CODE_URL      = "edb:terminal_code:edb_code:"     // 指标与终端关系的缓存
+
+	CACHE_KEY_REPLACE_EDB = "eta:replace_edb" //系统用户操作日志队列
 )
 
 // 模板消息推送类型