Browse Source

Merge branch 'master' into feature/eta1.2.0_edb_calculate

# Conflicts:
#	models/data_manage/edb_info.go
xyxie 1 year ago
parent
commit
6c1fe17631
95 changed files with 6766 additions and 1339 deletions
  1. 2 1
      .gitignore
  2. 1 1
      .idea/vcs.xml
  3. 3 1
      controllers/base_auth.go
  4. 3 1
      controllers/base_common.go
  5. 5 52
      controllers/data_manage/chart_classify.go
  6. 12 0
      controllers/data_manage/chart_common.go
  7. 54 12
      controllers/data_manage/chart_info.go
  8. 2 27
      controllers/data_manage/correlation/correlation_chart_classify.go
  9. 1 1
      controllers/data_manage/correlation/correlation_chart_info.go
  10. 1557 0
      controllers/data_manage/cross_variety/chart_info.go
  11. 422 0
      controllers/data_manage/cross_variety/classify.go
  12. 404 0
      controllers/data_manage/cross_variety/tag.go
  13. 295 0
      controllers/data_manage/cross_variety/variety.go
  14. 628 135
      controllers/data_manage/edb_info.go
  15. 3 28
      controllers/data_manage/future_good/future_good_chart_classify.go
  16. 2 2
      controllers/data_manage/future_good/future_good_chart_info.go
  17. 2 27
      controllers/data_manage/line_equation/line_chart_classify.go
  18. 1 1
      controllers/data_manage/line_equation/line_chart_info.go
  19. 1 1
      controllers/data_manage/line_feature/chart_info.go
  20. 2 27
      controllers/data_manage/line_feature/classify.go
  21. 6 6
      controllers/data_manage/predict_edb_info.go
  22. 10 0
      controllers/english_report/report.go
  23. 21 0
      controllers/error.go
  24. 30 0
      controllers/report.go
  25. 2 2
      controllers/sandbox/sandbox.go
  26. 42 24
      controllers/user_login.go
  27. BIN
      eta_mobile.exe
  28. 4 0
      main.go
  29. 15 0
      models/data_manage/chart_classify.go
  30. 7 7
      models/data_manage/chart_edb_mapping.go
  31. 38 19
      models/data_manage/chart_info.go
  32. 247 0
      models/data_manage/cross_variety/chart_info_cross_variety.go
  33. 148 0
      models/data_manage/cross_variety/chart_tag.go
  34. 239 0
      models/data_manage/cross_variety/chart_tag_variety.go
  35. 121 0
      models/data_manage/cross_variety/chart_variety.go
  36. 47 0
      models/data_manage/cross_variety/chart_variety_mapping.go
  37. 80 0
      models/data_manage/cross_variety/request/chart.go
  38. 31 0
      models/data_manage/cross_variety/request/tag.go
  39. 17 0
      models/data_manage/cross_variety/request/variety.go
  40. 21 0
      models/data_manage/cross_variety/response/chart.go
  41. 26 0
      models/data_manage/cross_variety/response/tag.go
  42. 19 0
      models/data_manage/cross_variety/response/variety.go
  43. 2 2
      models/data_manage/edb_data_baiinfo.go
  44. 79 31
      models/data_manage/edb_data_base.go
  45. 3 3
      models/data_manage/edb_data_calculate.go
  46. 1 1
      models/data_manage/edb_data_calculate_time_shift.go
  47. 3 3
      models/data_manage/edb_data_cffex.go
  48. 2 2
      models/data_manage/edb_data_coal.go
  49. 3 3
      models/data_manage/edb_data_dl.go
  50. 2 2
      models/data_manage/edb_data_gie.go
  51. 1 1
      models/data_manage/edb_data_insert_config.go
  52. 2 2
      models/data_manage/edb_data_lz.go
  53. 5 5
      models/data_manage/edb_data_manual.go
  54. 2 2
      models/data_manage/edb_data_sci.go
  55. 3 3
      models/data_manage/edb_data_sh.go
  56. 3 3
      models/data_manage/edb_data_shfe.go
  57. 63 0
      models/data_manage/edb_data_ths_ds.go
  58. 63 0
      models/data_manage/edb_data_wind_wsd.go
  59. 0 350
      models/data_manage/edb_data_zz.go
  60. 99 22
      models/data_manage/edb_info.go
  61. 1 167
      models/data_manage/edb_info_calculate.go
  62. 2 2
      models/data_manage/edb_info_calculate_bp.go
  63. 2 2
      models/data_manage/edb_info_calculate_hbz.go
  64. 2 2
      models/data_manage/edb_info_calculate_hcz.go
  65. 8 8
      models/data_manage/edb_info_calculate_ljztbpj.go
  66. 2 2
      models/data_manage/edb_info_calculate_ljzzy.go
  67. 2 2
      models/data_manage/edb_info_calculate_nszydpjjs.go
  68. 4 259
      models/data_manage/edb_info_calculate_tbz.go
  69. 2 2
      models/data_manage/edb_info_calculate_tcz.go
  70. 4 4
      models/data_manage/edb_info_calculate_zjpj.go
  71. 1 0
      models/data_manage/edb_source.go
  72. 7 0
      models/data_manage/response/chart.go
  73. 80 0
      models/data_stat/edb_info_delete_log.go
  74. 70 0
      models/data_stat/edb_info_update_log.go
  75. 12 0
      models/db.go
  76. 1 1
      models/sandbox/response/sandbox.go
  77. 31 15
      models/sandbox/sandbox.go
  78. 279 0
      routers/commentsRouter.go
  79. 9 0
      routers/router.go
  80. 30 0
      services/data/base_edb_lib.go
  81. 47 0
      services/data/chart_classify.go
  82. 118 16
      services/data/chart_info.go
  83. 4 4
      services/data/correlation/chart_info.go
  84. 809 0
      services/data/cross_variety/chart.go
  85. 3 2
      services/data/edb_classify.go
  86. 2 2
      services/data/edb_data.go
  87. 178 23
      services/data/edb_info.go
  88. 2 2
      services/data/edb_info_calculate.go
  89. 1 1
      services/data/future_good/chart_info.go
  90. 3 3
      services/data/predict_edb_info.go
  91. 1 1
      services/data/predict_edb_info_rule.go
  92. 61 0
      services/data_stat/edb_delete_log.go
  93. 55 0
      services/data_stat/edb_info_stat.go
  94. 24 7
      utils/constants.go
  95. 2 2
      utils/des3.go

+ 2 - 1
.gitignore

@@ -6,4 +6,5 @@
 /.idea
 /.idea/
 /.DS_Store
-*.tar.gz
+*.tar.gz
+eta_mobile.exe

+ 1 - 1
.idea/vcs.xml

@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <project version="4">
   <component name="VcsDirectoryMappings">
-    <mapping directory="" vcs="Git" />
+    <mapping directory="$PROJECT_DIR$" vcs="Git" />
   </component>
 </project>

+ 3 - 1
controllers/base_auth.go

@@ -227,6 +227,8 @@ func (c *BaseAuthController) ServeJSON(encoding ...bool) {
 
 func (c *BaseAuthController) JSON(data interface{}, hasIndent bool, coding bool) error {
 	c.Ctx.Output.Header("Content-Type", "application/json; charset=utf-8")
+	desEncrypt := utils.DesBase64Encrypt([]byte(utils.DesKey), utils.DesKeySalt)
+	c.Ctx.Output.Header("Dk", string(desEncrypt)) // des3加解密key
 	var content []byte
 	var err error
 	if hasIndent {
@@ -253,7 +255,7 @@ func (c *BaseAuthController) JSON(data interface{}, hasIndent bool, coding bool)
 
 	// 如果不是debug分支的话,那么需要加密返回
 	if utils.RunMode != "debug" {
-		content = utils.DesBase64Encrypt(content)
+		content = utils.DesBase64Encrypt(content, utils.DesKey)
 		// get请求时,不加双引号就获取不到数据,不知道什么原因,所以还是在前后加上双引号吧
 		content = []byte(`"` + string(content) + `"`)
 	}

+ 3 - 1
controllers/base_common.go

@@ -52,6 +52,8 @@ func (c *BaseCommonController) ServeJSON(encoding ...bool) {
 
 func (c *BaseCommonController) JSON(data interface{}, hasIndent bool, coding bool) error {
 	c.Ctx.Output.Header("Content-Type", "application/json; charset=utf-8")
+	desEncrypt := utils.DesBase64Encrypt([]byte(utils.DesKey), utils.DesKeySalt)
+	c.Ctx.Output.Header("Dk", string(desEncrypt)) // des3加解密key
 	var content []byte
 	var err error
 	if hasIndent {
@@ -75,7 +77,7 @@ func (c *BaseCommonController) JSON(data interface{}, hasIndent bool, coding boo
 
 	// 如果不是debug分支的话,那么需要加密返回
 	if utils.RunMode != "debug" {
-		content = utils.DesBase64Encrypt(content)
+		content = utils.DesBase64Encrypt(content, utils.DesKey)
 		// get请求时,不加双引号就获取不到数据,不知道什么原因,所以还是在前后加上双引号吧
 		content = []byte(`"` + string(content) + `"`)
 	}

+ 5 - 52
controllers/data_manage/chart_classify.go

@@ -62,7 +62,7 @@ func (this *ChartClassifyController) ChartClassifyListV2() {
 			return
 		}
 		// 移除没有权限的图表
-		allNodes := handleNoPermissionChart(allChartInfo, noPermissionChartIdMap)
+		allNodes := data.HandleNoPermissionChart(allChartInfo, noPermissionChartIdMap)
 		resp.AllNodes = allNodes
 
 		br.Ret = 200
@@ -77,11 +77,11 @@ func (this *ChartClassifyController) ChartClassifyListV2() {
 	key := utils.CACHE_CHART_CLASSIFY
 	if utils.Re == nil {
 		if utils.Re == nil && utils.Rc.IsExist(key) {
-			if data, err1 := utils.Rc.RedisBytes(key); err1 == nil {
-				err := json.Unmarshal(data, &resp)
+			if redisData, err1 := utils.Rc.RedisBytes(key); err1 == nil {
+				err := json.Unmarshal(redisData, &resp)
 				if err == nil && resp != nil {
 					// 移除没有权限的图表
-					allNodes := handleNoPermissionChart(resp.AllNodes, noPermissionChartIdMap)
+					allNodes := data.HandleNoPermissionChart(resp.AllNodes, noPermissionChartIdMap)
 					resp.AllNodes = allNodes
 
 					br.Ret = 200
@@ -157,7 +157,7 @@ func (this *ChartClassifyController) ChartClassifyListV2() {
 	}
 
 	// 移除没有权限的图表
-	allNodes := handleNoPermissionChart(resp.AllNodes, noPermissionChartIdMap)
+	allNodes := data.HandleNoPermissionChart(resp.AllNodes, noPermissionChartIdMap)
 	resp.AllNodes = allNodes
 
 	br.Ret = 200
@@ -215,53 +215,6 @@ func getChartClassifyListForMe(adminInfo system.Admin, resp *data_manage.ChartCl
 	return
 }
 
-// handleNoPermissionChart 图表列表返回,将没有权限的图表移除
-func handleNoPermissionChart(allNodes []*data_manage.ChartClassifyItems, noPermissionChartIdMap map[int]bool) (newAllNodes []*data_manage.ChartClassifyItems) {
-	// 移除没有权限的图表
-	newAllNodes = make([]*data_manage.ChartClassifyItems, 0)
-	for _, node := range allNodes {
-		// 二级分类
-		tmpNodeInfo := *node
-		tmpNodeList := make([]*data_manage.ChartClassifyItems, 0)
-		if node.Children != nil {
-			for _, chartList := range node.Children {
-				tmpInfo := *chartList
-				tmpList := make([]*data_manage.ChartClassifyItems, 0)
-
-				if chartList.Children != nil {
-					for _, chartInfo := range chartList.Children {
-						thirdInfo := *chartInfo
-						thirdList := make([]*data_manage.ChartClassifyItems, 0)
-						// 如果指标不可见,那么就不返回该指标
-						if _, ok := noPermissionChartIdMap[chartInfo.ChartInfoId]; ok {
-							continue
-						}
-						tmpList = append(tmpList, chartInfo)
-
-						if chartInfo.Children != nil {
-							for _, thirdChart := range chartInfo.Children {
-								// 如果指标不可见,那么就不返回该指标
-								if _, ok := noPermissionChartIdMap[chartInfo.ChartInfoId]; ok {
-									continue
-								}
-								thirdList = append(thirdList, thirdChart)
-							}
-						}
-						thirdInfo.Children = thirdList
-						tmpList = append(tmpList, &thirdInfo)
-					}
-				}
-				tmpInfo.Children = tmpList
-				tmpNodeList = append(tmpNodeList, &tmpInfo)
-			}
-		}
-		tmpNodeInfo.Children = tmpNodeList
-		newAllNodes = append(newAllNodes, &tmpNodeInfo)
-	}
-
-	return
-}
-
 // ChartClassifyItems
 // @Title 获取所有图表分类接口-不包含图表
 // @Description 获取所有图表分类接口-不包含图表

+ 12 - 0
controllers/data_manage/chart_common.go

@@ -3,6 +3,7 @@ package data_manage
 import (
 	"encoding/json"
 	"eta/eta_mobile/controllers/data_manage/correlation"
+	"eta/eta_mobile/controllers/data_manage/cross_variety"
 	"eta/eta_mobile/controllers/data_manage/future_good"
 	"eta/eta_mobile/controllers/data_manage/line_equation"
 	"eta/eta_mobile/models"
@@ -145,6 +146,17 @@ func (this *ChartInfoController) CommonChartInfoDetailFromUniqueCode() {
 		br.Success = true
 		br.Msg = "获取成功"
 		br.Data = resp
+	case utils.CHART_SOURCE_CROSS_HEDGING:
+		resp, isOk, msg, errMsg := cross_variety.GetChartInfoDetailFromUniqueCode(chartInfo, isCache, sysUser)
+		if !isOk {
+			br.Msg = msg
+			br.ErrMsg = errMsg
+			return
+		}
+		br.Ret = 200
+		br.Success = true
+		br.Msg = "获取成功"
+		br.Data = resp
 	default:
 		br.Msg = "错误的图表"
 		br.ErrMsg = "错误的图表"

+ 54 - 12
controllers/data_manage/chart_info.go

@@ -5,6 +5,7 @@ import (
 	"eta/eta_mobile/controllers"
 	"eta/eta_mobile/models"
 	"eta/eta_mobile/models/data_manage"
+	"eta/eta_mobile/models/data_manage/response"
 	"eta/eta_mobile/models/system"
 	"eta/eta_mobile/services"
 	"eta/eta_mobile/services/data"
@@ -942,14 +943,14 @@ func (this *ChartInfoController) ChartInfoEdbInfoDetail() {
 
 	switch edbInfo.EdbInfoType {
 	case 0: //普通源指标
-		dataList, err = data_manage.GetEdbDataList(edbInfo.Source, edbInfoId, startDateReal, endDate)
+		dataList, err = data_manage.GetEdbDataList(edbInfo.Source, edbInfo.SubSource, edbInfoId, startDateReal, endDate)
 		if err != nil {
 			br.Msg = "获取失败"
 			br.Msg = "获取失败,Err:" + err.Error()
 			return
 		}
 		//查询区间内最大最小值
-		minData, maxData, err = data_manage.GetEdbDataListMinAndMax(edbInfo.Source, edbInfoId, startDateReal, endDate)
+		minData, maxData, err = data_manage.GetEdbDataListMinAndMax(edbInfo.Source, edbInfo.SubSource, edbInfoId, startDateReal, endDate)
 		if err != nil {
 			br.Msg = "获取失败"
 			br.Msg = "获取指标最新的最大最小值失败,Err:" + err.Error()
@@ -966,7 +967,7 @@ func (this *ChartInfoController) ChartInfoEdbInfoDetail() {
 		// 有预测数据,且为普通的预测指标
 		if len(dataList) > 0 && edbInfo.EdbInfoType == 0 {
 			//查询区间内最大最小值
-			minData, maxData, err = data_manage.GetEdbDataListMinAndMax(sourceEdbInfoItem.Source, sourceEdbInfoItem.EdbInfoId, startDateReal, endDate)
+			minData, maxData, err = data_manage.GetEdbDataListMinAndMax(sourceEdbInfoItem.Source, sourceEdbInfoItem.SubSource, sourceEdbInfoItem.EdbInfoId, startDateReal, endDate)
 			if err != nil {
 				br.Msg = "获取失败"
 				br.Msg = "获取指标最新的最大最小值失败,Err:" + err.Error()
@@ -1329,7 +1330,7 @@ func (this *ChartInfoController) ChartInfoSearchByEs() {
 	if keyword != "" {
 		searchList, total, err = data.EsSearchChartInfo(keyword, showSysId, []int{utils.CHART_SOURCE_DEFAULT}, noPermissionChartIdList, startSize, pageSize)
 	} else {
-		total, searchList, err = data_manage.ChartInfoSearchByEmptyKeyWord(showSysId, []int{utils.CHART_SOURCE_DEFAULT}, noPermissionChartIdList)
+		total, searchList, err = data_manage.ChartInfoSearchByEmptyKeyWord(showSysId, []int{utils.CHART_SOURCE_DEFAULT}, noPermissionChartIdList, startSize, pageSize)
 		if err != nil && err.Error() != utils.ErrNoRow() {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取图表信息失败,Err:" + err.Error()
@@ -1493,21 +1494,22 @@ func (this *ChartInfoController) BatchChartInfoRefresh() {
 		return
 	}
 
-	err = data.BatchChartInfoRefreshV2(chartInfoList)
+	redisKey := data.GetBatchChartRefreshKey(req.Source, req.ReportId, req.ReportChapterId)
+
+	// 图表中的指标刷新
+	err, isAsync := data.BatchChartInfoRefreshV2(chartInfoList, redisKey)
 	if err != nil {
 		br.Msg = "刷新失败"
 		br.ErrMsg = "刷新图表关联指标信息失败,Err:" + err.Error()
 		return
 	}
-
-	//清除图表缓存
-	for _, v := range chartInfoList {
-		key := utils.HZ_CHART_LIB_DETAIL + v.UniqueCode
-		_ = utils.Rc.Delete(key)
+	br.Msg = "刷新成功"
+	if isAsync {
+		br.Msg = "研报中图表关联指标较多,请10分钟后刷新页面查看最新数据"
 	}
+
 	br.Ret = 200
 	br.Success = true
-	br.Msg = "刷新成功"
 }
 
 // @Title 保存图表接口
@@ -1794,4 +1796,44 @@ func (this *ChartInfoController) ChartInfoImageSet() {
 	br.Ret = 200
 	br.Success = true
 	br.Msg = "保存成功"
-}
+}
+
+// GetBatchChartRefreshResult
+// @Title 获取批量刷新图表结果的接口
+// @Description 获取批量刷新图表结果的接口
+// @Param	request	body data_manage.BatchChartRefreshReq true "type json string"
+// @Success Ret=200 刷新成功
+// @router /chart_info/batch_refresh/result [post]
+func (this *EdbInfoController) GetBatchChartRefreshResult() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	var req data_manage.BatchChartRefreshReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	// 刷新结果,默认是刷新完成了
+	refreshResult := data.CheckBatchChartRefreshResult(req.Source, req.ReportId, req.ReportChapterId)
+
+	resp := response.ChartRefreshResp{
+		RefreshResult: refreshResult,
+	}
+
+	br.Data = resp
+	br.Ret = 200
+	br.Success = true
+
+}

+ 2 - 27
controllers/data_manage/correlation/correlation_chart_classify.go

@@ -4,6 +4,7 @@ import (
 	"eta/eta_mobile/controllers"
 	"eta/eta_mobile/models"
 	"eta/eta_mobile/models/data_manage"
+	"eta/eta_mobile/services/data"
 	"eta/eta_mobile/utils"
 )
 
@@ -99,7 +100,7 @@ func (this *CorrelationChartClassifyController) ChartClassifyList() {
 	}
 
 	// 移除没有权限的图表
-	allNodes := handleNoPermissionChart(rootList, noPermissionChartIdMap)
+	allNodes := data.HandleNoPermissionChart(rootList, noPermissionChartIdMap)
 	resp.AllNodes = allNodes
 
 	br.Ret = 200
@@ -107,29 +108,3 @@ func (this *CorrelationChartClassifyController) ChartClassifyList() {
 	br.Msg = "获取成功"
 	br.Data = resp
 }
-
-// handleNoPermissionChart 图表列表返回,将没有权限的图表移除
-func handleNoPermissionChart(allNodes []*data_manage.ChartClassifyItems, noPermissionChartIdMap map[int]bool) (newAllNodes []*data_manage.ChartClassifyItems) {
-	// 移除没有权限的图表
-	newAllNodes = make([]*data_manage.ChartClassifyItems, 0)
-	for _, node := range allNodes {
-		// 二级分类
-		tmpNodeInfo := *node
-		tmpNodeList := make([]*data_manage.ChartClassifyItems, 0)
-
-		if node.Children != nil {
-			for _, chartInfo := range node.Children {
-				// 如果指标不可见,那么就不返回该指标
-				if _, ok := noPermissionChartIdMap[chartInfo.ChartInfoId]; ok {
-					continue
-				}
-				tmpNodeList = append(tmpNodeList, chartInfo)
-			}
-		}
-
-		tmpNodeInfo.Children = tmpNodeList
-		newAllNodes = append(newAllNodes, &tmpNodeInfo)
-	}
-
-	return
-}

+ 1 - 1
controllers/data_manage/correlation/correlation_chart_info.go

@@ -739,7 +739,7 @@ func (this *CorrelationChartInfoController) SearchByEs() {
 	if keyword != "" {
 		searchList, total, err = data.EsSearchChartInfo(keyword, showSysId, sourceList, noPermissionChartIdList, startSize, pageSize)
 	} else {
-		total, searchList, err = data_manage.ChartInfoSearchByEmptyKeyWord(showSysId, sourceList, noPermissionChartIdList)
+		total, searchList, err = data_manage.ChartInfoSearchByEmptyKeyWord(showSysId, sourceList, noPermissionChartIdList, startSize, pageSize)
 		if err != nil && err.Error() != utils.ErrNoRow() {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取图表信息失败,Err:" + err.Error()

+ 1557 - 0
controllers/data_manage/cross_variety/chart_info.go

@@ -0,0 +1,1557 @@
+package cross_variety
+
+import (
+	"encoding/json"
+	"eta/eta_mobile/controllers"
+	"eta/eta_mobile/models"
+	"eta/eta_mobile/models/data_manage"
+	cross_varietyModels "eta/eta_mobile/models/data_manage/cross_variety"
+	"eta/eta_mobile/models/data_manage/cross_variety/request"
+	"eta/eta_mobile/models/data_manage/cross_variety/response"
+	"eta/eta_mobile/models/system"
+	"eta/eta_mobile/services/data"
+	"eta/eta_mobile/services/data/cross_variety"
+	"eta/eta_mobile/utils"
+	"fmt"
+	"github.com/rdlucklib/rdluck_tools/paging"
+	"strconv"
+	"strings"
+	"time"
+)
+
+// ChartInfoController
+// @Description: 跨品种分析图表
+type ChartInfoController struct {
+	controllers.BaseAuthController
+}
+
+// List
+// @Title 跨品种分析图表列表接口
+// @Description 跨品种分析图表列表接口
+// @Param   PageSize   query   int  true       "每页数据条数"
+// @Param   CurrentIndex   query   int  true       "当前页页码,从1开始"
+// @Param   ChartClassifyId   query   int  true       "分类id"
+// @Param   Keyword   query   string  true       "搜索关键词"
+// @Param   IsShowMe   query   bool  true       "是否只看我的,true、false"
+// @Param   Source   query   int  true       "图表类型,10:跨品种分析
+// @Success 200 {object} data_manage.ChartListResp
+// @router /chart_info/list [get]
+func (c *ChartInfoController) List() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	sysUser := c.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+
+	chartClassifyId, _ := c.GetInt("ChartClassifyId")
+
+	pageSize, _ := c.GetInt("PageSize")
+	currentIndex, _ := c.GetInt("CurrentIndex")
+	keyword := c.GetString("KeyWord")
+
+	var total int
+	page := paging.GetPaging(currentIndex, pageSize, total)
+
+	var startSize int
+	if pageSize <= 0 {
+		pageSize = utils.PageSize20
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	startSize = paging.StartIndex(currentIndex, pageSize)
+
+	source, _ := c.GetInt("Source")
+	if source <= 0 {
+		source = utils.CHART_SOURCE_CROSS_HEDGING
+	}
+
+	var condition string
+	var pars []interface{}
+
+	// 普通图表
+	condition += ` AND source = ? `
+	pars = append(pars, source)
+
+	if chartClassifyId > 0 {
+		chartClassifyId, err := data_manage.GetChartClassify(chartClassifyId)
+		if err != nil && err.Error() != utils.ErrNoRow() {
+			br.Msg = "获取图表信息失败"
+			br.ErrMsg = "获取信息失败,GetChartClassify,Err:" + err.Error()
+			return
+		}
+		condition += " AND chart_classify_id IN(" + chartClassifyId + ") "
+	}
+	if keyword != "" {
+		condition += ` AND  ( chart_name LIKE '%` + keyword + `%' )`
+	}
+
+	//只看我的
+	isShowMe, _ := c.GetBool("IsShowMe")
+	if isShowMe {
+		condition += ` AND sys_user_id = ? `
+		pars = append(pars, sysUser.AdminId)
+	}
+
+	// 获取当前账号的不可见指标
+	noPermissionChartIdList := make([]int, 0)
+	{
+		obj := data_manage.EdbInfoNoPermissionAdmin{}
+		confList, err := obj.GetAllChartListByAdminId(c.SysUser.AdminId)
+		if err != nil && err.Error() != utils.ErrNoRow() {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取不可见指标配置数据失败,Err:" + err.Error()
+			return
+		}
+		for _, v := range confList {
+			noPermissionChartIdList = append(noPermissionChartIdList, v.ChartInfoId)
+		}
+	}
+
+	lenNoPermissionChartIdList := len(noPermissionChartIdList)
+	if lenNoPermissionChartIdList > 0 {
+		condition += ` AND chart_info_id not in (` + utils.GetOrmInReplace(lenNoPermissionChartIdList) + `) `
+		pars = append(pars, noPermissionChartIdList)
+	}
+
+	//获取图表信息
+	list, err := data_manage.GetChartListByCondition(condition, pars, startSize, pageSize)
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		br.Success = true
+		br.Msg = "获取图表信息失败"
+		br.ErrMsg = "获取图表信息失败,Err:" + err.Error()
+		return
+	}
+
+	myChartList, err := data_manage.GetMyChartListByAdminId(sysUser.AdminId)
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		br.Msg = "获取图表信息失败"
+		br.ErrMsg = "获取我的图表信息失败,Err:" + err.Error()
+		return
+	}
+	myChartMap := make(map[int]*data_manage.MyChartView)
+	for _, v := range myChartList {
+		myChartMap[v.ChartInfoId] = v
+	}
+	listLen := len(list)
+	chartEdbMap := make(map[int][]*data_manage.ChartEdbInfoMapping)
+	if listLen > 0 {
+		chartInfoIds := ""
+		for _, v := range list {
+			chartInfoIds += strconv.Itoa(v.ChartInfoId) + ","
+		}
+		if chartInfoIds != "" {
+			chartInfoIds = strings.Trim(chartInfoIds, ",")
+			//判断是否需要展示英文标识
+			edbList, e := data_manage.GetChartEdbMappingListByChartInfoIds(chartInfoIds)
+			if e != nil {
+				br.Msg = "获取失败"
+				br.ErrMsg = "获取图表,指标信息失败,Err:" + e.Error()
+				return
+			}
+			for _, v := range edbList {
+				chartEdbMap[v.ChartInfoId] = append(chartEdbMap[v.ChartInfoId], v)
+			}
+		}
+	}
+	for i := 0; i < listLen; i++ {
+		//判断是否需要展示英文标识
+		if edbTmpList, ok := chartEdbMap[list[i].ChartInfoId]; ok {
+			list[i].IsEnChart = data.CheckIsEnChart(list[i].ChartNameEn, edbTmpList, list[i].Source, list[i].ChartType)
+		}
+
+		if existItem, ok := myChartMap[list[i].ChartInfoId]; ok {
+			list[i].IsAdd = true
+			list[i].MyChartId = existItem.MyChartId
+			list[i].MyChartClassifyId = existItem.MyChartClassifyId
+		}
+	}
+
+	resp := new(data_manage.ChartListResp)
+	if list == nil || len(list) <= 0 || (err != nil && err.Error() == utils.ErrNoRow()) {
+		items := make([]*data_manage.ChartInfoView, 0)
+		resp.Paging = page
+		resp.List = items
+		br.Ret = 200
+		br.Success = true
+		br.Msg = "获取成功"
+		return
+	}
+
+	dataCount, err := data_manage.GetChartListCountByCondition(condition, pars)
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		br.Msg = "获取指标信息失败"
+		br.ErrMsg = "获取指标数据总数失败,Err:" + err.Error()
+		return
+	}
+	page = paging.GetPaging(currentIndex, pageSize, dataCount)
+	resp.Paging = page
+	resp.List = list
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+// Preview
+// @Title 跨品种分析图表-预览数据
+// @Description 跨品种分析图表-获取预览数据
+// // @Param	request	body request.ChartConfigReq true "type json string"
+// @Success 200 {object} data_manage.ChartEdbInfoDetailResp
+// @router /chart_info/preview [post]
+func (c *ChartInfoController) Preview() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	sysUser := c.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	var req request.ChartConfigReq
+	if err := json.Unmarshal(c.Ctx.Input.RequestBody, &req); err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	if req.TagX <= 0 {
+		br.Msg = "请选择X轴坐标的标签"
+		br.IsSendEmail = false
+		return
+	}
+
+	if req.TagY <= 0 {
+		br.Msg = "请选择Y轴坐标的标签"
+		br.IsSendEmail = false
+		return
+	}
+
+	if req.CalculateValue <= 0 {
+		br.Msg = "请设置时间长度"
+		br.IsSendEmail = false
+		return
+	}
+	if req.CalculateUnit == `` {
+		br.Msg = "请设置时间频度"
+		br.IsSendEmail = false
+		return
+	}
+
+	// 品种配置
+	varietyListList := len(req.VarietyList)
+	if varietyListList < 0 {
+		br.Msg = "请选择品种"
+		br.IsSendEmail = false
+		return
+	}
+
+	// 日期配置
+	dateConfigList := len(req.DateConfigList)
+	if dateConfigList < 0 {
+		br.Msg = "请选择日期"
+		br.IsSendEmail = false
+		return
+	}
+	if dateConfigList > 5 {
+		br.Msg = "日期数量已达上限!"
+		br.IsSendEmail = false
+		return
+	}
+
+	chartInfo := new(data_manage.ChartInfoView)
+	chartInfo.ChartType = utils.CHART_SOURCE_CROSS_HEDGING
+
+	// 获取图表x轴y轴
+	edbInfoList, dataResp, err, errMsg, isSendEmail := cross_variety.GetChartData(0, req)
+	if err != nil {
+		br.IsSendEmail = isSendEmail
+		br.Msg = "获取失败"
+		if errMsg != `` {
+			br.Msg = errMsg
+		}
+		br.ErrMsg = "获取图表,指标信息失败,Err:" + err.Error()
+		return
+	}
+
+	resp := response.ChartPreviewResp{
+		EdbInfoList: edbInfoList,
+		DataResp:    dataResp,
+	}
+	//resp.EdbInfoList = edbList
+	br.Data = resp
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+}
+
+// Add
+// @Title 新增图表接口
+// @Description 新增图表接口
+// @Param	request	body request.AddChartInfoReq true "type json string"
+// @Success 200 {object} data_manage.AddChartInfoResp
+// @router /chart_info/add [post]
+func (c *ChartInfoController) Add() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+
+	sysUser := c.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+
+	cacheKey := "CACHE_CHART_INFO_ADD_" + strconv.Itoa(sysUser.AdminId)
+	if !utils.Rc.SetNX(cacheKey, 1, 30*time.Second) {
+		br.Msg = "系统处理中,请稍后重试!"
+		br.ErrMsg = "系统处理中,请稍后重试!" + sysUser.RealName + ";data:" + string(c.Ctx.Input.RequestBody)
+		return
+	}
+	defer func() {
+		_ = utils.Rc.Delete(cacheKey)
+	}()
+
+	var req request.AddChartReq
+	err := json.Unmarshal(c.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	// 添加图表
+	chartInfo, err, errMsg, isSendEmail := cross_variety.AddChartInfo(req, sysUser)
+	if err != nil {
+		br.Msg = "保存失败"
+		if errMsg != `` {
+			br.Msg = errMsg
+		}
+		br.ErrMsg = err.Error()
+		br.IsSendEmail = isSendEmail
+		return
+	}
+
+	//新增操作日志
+	{
+		chartLog := new(data_manage.ChartInfoLog)
+		chartLog.ChartInfoId = chartInfo.ChartInfoId
+		chartLog.ChartName = req.ChartName
+		chartLog.ChartClassifyId = chartInfo.ChartClassifyId
+		chartLog.SysUserId = sysUser.AdminId
+		chartLog.SysUserRealName = sysUser.RealName
+		chartLog.UniqueCode = chartInfo.UniqueCode
+		chartLog.CreateTime = time.Now()
+		chartLog.Content = string(c.Ctx.Input.RequestBody)
+		chartLog.Status = "新增跨品种分析图表"
+		chartLog.Method = c.Ctx.Input.URI()
+		go data_manage.AddChartInfoLog(chartLog)
+	}
+
+	resp := new(data_manage.AddChartInfoResp)
+	resp.ChartInfoId = chartInfo.ChartInfoId
+	resp.UniqueCode = chartInfo.UniqueCode
+	resp.ChartType = chartInfo.ChartType
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "保存成功"
+	br.Data = resp
+	br.IsAddLog = true
+}
+
+// Edit
+// @Title 编辑图表接口
+// @Description 编辑图表接口
+// @Param	request	body request.EditChartInfoReq true "type json string"
+// @Success Ret=200 保存成功
+// @router /chart_info/edit [post]
+func (c *ChartInfoController) Edit() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+
+	sysUser := c.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+
+	var req request.EditChartReq
+	err := json.Unmarshal(c.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	chartItem, err, errMsg, isSendEmail := cross_variety.EditChartInfo(req, sysUser)
+	if err != nil {
+		br.Msg = "保存失败"
+		if errMsg != `` {
+			br.Msg = errMsg
+		}
+		br.ErrMsg = err.Error()
+		br.IsSendEmail = isSendEmail
+		return
+	}
+
+	resp := new(data_manage.AddChartInfoResp)
+	resp.ChartInfoId = chartItem.ChartInfoId
+	resp.UniqueCode = chartItem.UniqueCode
+	//resp.ChartType = req.ChartType
+
+	//新增操作日志
+	{
+		chartLog := new(data_manage.ChartInfoLog)
+		chartLog.ChartName = chartItem.ChartName
+		chartLog.ChartInfoId = req.ChartInfoId
+		chartLog.ChartClassifyId = chartItem.ChartClassifyId
+		chartLog.SysUserId = sysUser.AdminId
+		chartLog.SysUserRealName = sysUser.RealName
+		chartLog.UniqueCode = chartItem.UniqueCode
+		chartLog.CreateTime = time.Now()
+		chartLog.Content = string(c.Ctx.Input.RequestBody)
+		chartLog.Status = "编辑跨品种分析图表"
+		chartLog.Method = c.Ctx.Input.URL()
+		go data_manage.AddChartInfoLog(chartLog)
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "保存成功"
+	br.Data = resp
+	br.IsAddLog = true
+}
+
+// Detail
+// @Title 获取图表详情
+// @Description 获取图表详情接口
+// @Param   ChartInfoId   query   int  true       "图表id"
+// @Success 200 {object} data_manage.ChartInfoDetailResp
+// @router /chart_info/detail [get]
+func (c *ChartInfoController) Detail() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	sysUser := c.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	chartInfoId, _ := c.GetInt("ChartInfoId")
+	if chartInfoId <= 0 {
+		br.Msg = "参数有误"
+		return
+	}
+
+	var err error
+	chartInfo := new(data_manage.ChartInfoView)
+	chartInfo, err = data_manage.GetChartInfoViewById(chartInfoId)
+	if err != nil {
+		if err.Error() == utils.ErrNoRow() {
+			br.Msg = "图被删除,请刷新页面"
+			br.ErrMsg = "图被删除,请刷新页面,Err:" + err.Error()
+			return
+		}
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取图表信息失败,Err:" + err.Error()
+		return
+	}
+
+	if chartInfo.ExtraConfig == `` {
+		br.Msg = "图表配置信息异常"
+		br.ErrMsg = "图表配置信息异常"
+		br.IsSendEmail = false
+		return
+	}
+	var config request.ChartConfigReq
+	err = json.Unmarshal([]byte(chartInfo.ExtraConfig), &config)
+	if err != nil {
+		br.Msg = "解析跨品种分析配置失败"
+		br.ErrMsg = "解析跨品种分析配置失败,Err:" + err.Error()
+		return
+	}
+
+	//mappingList, err := cross_varietyModel.GetChartVarietyMappingList(chartInfo.ChartInfoId)
+	//if err != nil {
+	//	br.Msg = "获取品种失败"
+	//	br.ErrMsg = "获取品种失败,Err:" + err.Error()
+	//	return
+	//}
+	// 获取跨品种分析配置
+	//chartInfoCrossVariety, err := cross_varietyModel.GetChartInfoCrossVarietyByChartInfoId(chartInfo.ChartInfoId)
+	//if err != nil {
+	//	br.Msg = "获取跨品种分析配置失败"
+	//	br.ErrMsg = "获取跨品种分析配置失败,Err:" + err.Error()
+	//	return
+	//}
+	//
+	//varietyIdList := make([]int,0)
+	//for _,v:=range mappingList{
+	//	varietyIdList = append(varietyIdList,v.ChartVarietyId)
+	//}
+	//config := request.ChartConfigReq{
+	//	TagX:           chartInfoCrossVariety.ChartXTagId,
+	//	TagY:           chartInfoCrossVariety.ChartYTagId,
+	//	CalculateValue: chartInfoCrossVariety.CalculateValue,
+	//	CalculateUnit:  chartInfoCrossVariety.CalculateUnit,
+	//	DateConfigList: config.DateConfigList,
+	//	VarietyList:    varietyIdList,
+	//}
+	//config.TagX =
+
+	// 获取图表x轴y轴
+	edbList, dataResp, err, errMsg, isSendEmail := cross_variety.GetChartData(0, config)
+	if err != nil {
+		br.IsSendEmail = isSendEmail
+		br.Msg = "获取失败"
+		if errMsg != `` {
+			br.Msg = errMsg
+		}
+		br.ErrMsg = "获取图表,指标信息失败,Err:" + err.Error()
+		return
+	}
+
+	// 完善指标信息
+	//edbList, e := correlationServ.GetChartEdbInfoFormat(chartInfo.ChartInfoId, edbInfoMappingA, edbInfoMappingB)
+	//if e != nil {
+	//	br.Msg = "获取失败"
+	//	br.ErrMsg = "获取跨品种分析图表, 完善指标信息失败, Err:" + e.Error()
+	//	return
+	//}
+
+	// 判断是否加入我的图库
+	if chartInfoId > 0 && chartInfo != nil {
+		{
+			var myChartCondition string
+			var myChartPars []interface{}
+			myChartCondition += ` AND a.admin_id=? `
+			myChartPars = append(myChartPars, sysUser.AdminId)
+			myChartCondition += ` AND a.chart_info_id=? `
+			myChartPars = append(myChartPars, chartInfo.ChartInfoId)
+
+			myChartList, err := data_manage.GetMyChartByCondition(myChartCondition, myChartPars)
+			if err != nil && err.Error() != utils.ErrNoRow() {
+				br.Msg = "获取失败"
+				br.ErrMsg = "获取我的图表信息失败,GetMyChartByCondition,Err:" + err.Error()
+				return
+			}
+			if myChartList != nil && len(myChartList) > 0 {
+				chartInfo.IsAdd = true
+				chartInfo.MyChartId = myChartList[0].MyChartId
+				chartInfo.MyChartClassifyId = myChartList[0].MyChartClassifyId
+			}
+		}
+	}
+
+	//图表操作权限
+	chartInfo.IsEdit = data.CheckOpChartPermission(sysUser, chartInfo.SysUserId)
+	////判断是否需要展示英文标识
+	//chartInfo.IsEnChart = data.CheckIsEnChart(chartInfo.ChartNameEn, edbList[0:1], chartInfo.Source, chartInfo.ChartType)
+	//chartInfo.UnitEn = edbInfoMappingA.UnitEn
+
+	// 另存为
+	chartInfo.Button = data_manage.ChartViewButton{
+		IsEdit:    chartInfo.IsEdit,
+		IsEnChart: chartInfo.IsEnChart,
+		IsAdd:     chartInfo.IsAdd,
+		IsCopy:    true,
+		IsSetName: chartInfo.IsSetName,
+	}
+
+	resp := new(data_manage.ChartInfoDetailResp)
+	resp.ChartInfo = chartInfo
+	resp.DataResp = dataResp
+	resp.EdbInfoList = edbList
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+// Relation
+// @Title 获取图表的关联信息
+// @Description 获取图表的关联信息
+// @Param   ChartInfoId   query   int  true       "图表id"
+// @Success 200 {object} data_manage.ChartInfoDetailResp
+// @router /chart_info/relation [get]
+func (c *ChartInfoController) Relation() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	sysUser := c.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	chartInfoId, _ := c.GetInt("ChartInfoId")
+	if chartInfoId <= 0 {
+		br.Msg = "参数有误"
+		return
+	}
+
+	var err error
+	chartInfo := new(data_manage.ChartInfoView)
+	chartInfo, err = data_manage.GetChartInfoViewById(chartInfoId)
+	if err != nil {
+		if err.Error() == utils.ErrNoRow() {
+			br.Msg = "图被删除,请刷新页面"
+			br.ErrMsg = "图被删除,请刷新页面,Err:" + err.Error()
+			return
+		}
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取图表信息失败,Err:" + err.Error()
+		return
+	}
+
+	if chartInfo.ExtraConfig == `` {
+		br.Msg = "图表配置信息异常"
+		br.ErrMsg = "图表配置信息异常"
+		br.IsSendEmail = false
+		return
+	}
+	var config request.ChartConfigReq
+	err = json.Unmarshal([]byte(chartInfo.ExtraConfig), &config)
+	if err != nil {
+		br.Msg = "解析跨品种分析配置失败"
+		br.ErrMsg = "解析跨品种分析配置失败,Err:" + err.Error()
+		return
+	}
+
+	tmpTagList, err := cross_varietyModels.GetTagListByIdList([]int{config.TagX, config.TagY})
+	if err != nil {
+		br.Msg = "获取标签信息失败"
+		br.ErrMsg = "获取标签信息失败,Err:" + err.Error()
+		return
+	}
+
+	var xTag, yTag *cross_varietyModels.ChartTag
+	for _, v := range tmpTagList {
+		if v.ChartTagId == config.TagX {
+			xTag = v
+		} else {
+			yTag = v
+		}
+	}
+	tagList := []*cross_varietyModels.ChartTag{
+		xTag, yTag,
+	}
+
+	// 获取品种列表
+	varietyList, err := cross_varietyModels.GetVarietyListByIdList(config.VarietyList)
+	if err != nil {
+		br.Msg = "获取品种信息失败"
+		br.ErrMsg = "获取品种信息失败,Err:" + err.Error()
+		return
+	}
+	resp := response.ChartRelationResp{
+		ChartInfo:   chartInfo,
+		TagList:     tagList,
+		VarietyList: varietyList,
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+// Copy
+// @Title 复制并新增图表接口
+// @Description 新增图表接口
+// @Param	request	body data_manage.CopyAddChartInfoReq true "type json string"
+// @Success 200 {object} data_manage.AddChartInfoResp
+// @router /chart_info/copy [post]
+func (c *ChartInfoController) Copy() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+
+	sysUser := c.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	deleteCache := true
+	cacheKey := "CACHE_CHART_INFO_ADD_" + strconv.Itoa(sysUser.AdminId)
+	defer func() {
+		if deleteCache {
+			utils.Rc.Delete(cacheKey)
+		}
+	}()
+	if !utils.Rc.SetNX(cacheKey, 1, 30*time.Second) {
+		deleteCache = false
+		br.Msg = "系统处理中,请稍后重试!"
+		br.ErrMsg = "系统处理中,请稍后重试!" + sysUser.RealName + ";data:" + string(c.Ctx.Input.RequestBody)
+		return
+	}
+	var req request.CopyAddChartInfoReq
+	err := json.Unmarshal(c.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	// 获取原图表信息
+	oldChartInfo, err := data_manage.GetChartInfoById(req.ChartInfoId)
+	if err != nil {
+		br.Msg = "获取原图表信息失败"
+		br.ErrMsg = "获取原图表信息失败,Err:" + err.Error()
+		return
+	}
+
+	var config request.AddChartReq
+	err = json.Unmarshal([]byte(oldChartInfo.ExtraConfig), &config)
+	if err != nil {
+		br.Msg = "原图表信息配置解析异常!"
+		br.ErrMsg = "原图表信息配置解析失败,Err:" + err.Error()
+		return
+	}
+	config.ChartName = req.ChartName
+
+	// 添加图表
+	chartInfo, err, errMsg, isSendEmail := cross_variety.AddChartInfo(config, sysUser)
+	if err != nil {
+		br.Msg = "保存失败"
+		if errMsg != `` {
+			br.Msg = errMsg
+		}
+		br.ErrMsg = err.Error()
+		br.IsSendEmail = isSendEmail
+		return
+	}
+
+	if err != nil {
+		br.Msg = "保存失败"
+		if errMsg != `` {
+			br.Msg = errMsg
+		}
+		br.ErrMsg = err.Error()
+		br.IsSendEmail = isSendEmail
+		return
+	}
+
+	//新增操作日志
+	{
+		chartLog := new(data_manage.ChartInfoLog)
+		chartLog.ChartInfoId = chartInfo.ChartInfoId
+		chartLog.ChartName = req.ChartName
+		chartLog.ChartClassifyId = chartInfo.ChartClassifyId
+		chartLog.SysUserId = sysUser.AdminId
+		chartLog.SysUserRealName = sysUser.RealName
+		chartLog.UniqueCode = chartInfo.UniqueCode
+		chartLog.CreateTime = time.Now()
+		chartLog.Content = string(c.Ctx.Input.RequestBody)
+		chartLog.Status = "复制跨品种分析图表"
+		chartLog.Method = c.Ctx.Input.URI()
+		go data_manage.AddChartInfoLog(chartLog)
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "保存成功"
+	br.Data = data_manage.AddChartInfoResp{
+		ChartInfoId: chartInfo.ChartInfoId,
+		UniqueCode:  chartInfo.UniqueCode,
+		ChartType:   chartInfo.ChartType,
+	}
+	br.IsAddLog = true
+}
+
+// Move
+// @Title 移动图表接口
+// @Description 移动图表接口
+// @Success 200 {object} data_manage.MoveChartInfoReq
+// @router /chart_info/move [post]
+func (c *ChartInfoController) Move() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+
+	sysUser := c.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+
+	var req data_manage.MoveChartInfoReq
+	err := json.Unmarshal(c.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	if req.ChartInfoId <= 0 {
+		br.Msg = "参数错误"
+		br.ErrMsg = "图表id小于等于0"
+		br.IsSendEmail = false
+		return
+	}
+
+	chartInfo, err := data_manage.GetChartInfoById(req.ChartInfoId)
+	if err != nil {
+		br.Msg = "移动失败"
+		br.ErrMsg = "获取图表信息失败,Err:" + err.Error()
+		return
+	}
+
+	if chartInfo.Source != utils.CHART_SOURCE_CROSS_HEDGING {
+		br.Msg = "图表异常"
+		br.ErrMsg = "分类异常,不是跨品种分析的图表"
+		return
+	}
+
+	//移动排序
+	updateCol := make([]string, 0)
+	//如果有传入 上一个兄弟节点分类id
+	if req.PrevChartInfoId > 0 {
+		prevChartInfo, err := data_manage.GetChartInfoById(req.PrevChartInfoId)
+		if err != nil {
+			br.Msg = "移动失败"
+			br.ErrMsg = "获取上一个兄弟节点分类信息失败,Err:" + err.Error()
+			return
+		}
+		if prevChartInfo.ChartClassifyId != chartInfo.ChartClassifyId {
+			br.Msg = "不允许跨分类移动"
+			br.ErrMsg = "不允许跨分类移动"
+			br.IsSendEmail = false
+			return
+		}
+
+		//如果是移动在两个兄弟节点之间
+		if req.NextChartInfoId > 0 {
+			//下一个兄弟节点
+			nextChartInfo, err := data_manage.GetChartInfoById(req.NextChartInfoId)
+			if err != nil {
+				br.Msg = "移动失败"
+				br.ErrMsg = "获取下一个兄弟节点分类信息失败,Err:" + err.Error()
+				return
+			}
+			//如果上一个兄弟与下一个兄弟的排序权重是一致的,那么需要将下一个兄弟(以及下个兄弟的同样排序权重)的排序权重+2,自己变成上一个兄弟的排序权重+1
+			if prevChartInfo.Sort == nextChartInfo.Sort || prevChartInfo.Sort == chartInfo.Sort {
+				//变更兄弟节点的排序
+				updateSortStr := `sort + 2`
+				_ = data_manage.UpdateChartInfoSortByClassifyId(prevChartInfo.ChartClassifyId, prevChartInfo.Sort, prevChartInfo.ChartInfoId, []int{chartInfo.Source}, updateSortStr)
+			} else {
+				//如果下一个兄弟的排序权重正好是上个兄弟节点的下一层,那么需要再加一层了
+				if nextChartInfo.Sort-prevChartInfo.Sort == 1 {
+					//变更兄弟节点的排序
+					updateSortStr := `sort + 1`
+					_ = data_manage.UpdateChartInfoSortByClassifyId(prevChartInfo.ChartClassifyId, prevChartInfo.Sort, prevChartInfo.ChartInfoId, []int{chartInfo.Source}, updateSortStr)
+				}
+			}
+		}
+
+		chartInfo.Sort = prevChartInfo.Sort + 1
+		chartInfo.ModifyTime = time.Now()
+		updateCol = append(updateCol, "Sort", "ModifyTime")
+
+	} else {
+		firstClassify, err := data_manage.GetFirstChartInfoByClassifyId(chartInfo.ChartClassifyId)
+		if err != nil && err.Error() != utils.ErrNoRow() {
+			br.Msg = "移动失败"
+			br.ErrMsg = "获取获取当前父级分类下的排序第一条的分类信息失败,Err:" + err.Error()
+			return
+		}
+
+		if firstClassify != nil && firstClassify.ChartClassifyId != chartInfo.ChartClassifyId {
+			br.Msg = "不允许跨分类移动"
+			br.ErrMsg = "不允许跨分类移动"
+			br.IsSendEmail = false
+			return
+		}
+
+		//如果该分类下存在其他分类,且第一个其他分类的排序等于0,那么需要调整排序
+		if firstClassify != nil && firstClassify.Sort == 0 {
+			updateSortStr := ` sort + 1 `
+			_ = data_manage.UpdateChartInfoSortByClassifyId(firstClassify.ChartClassifyId, 0, firstClassify.ChartInfoId-1, []int{chartInfo.Source}, updateSortStr)
+		}
+
+		chartInfo.Sort = 0 //那就是排在第一位
+		chartInfo.ModifyTime = time.Now()
+		updateCol = append(updateCol, "Sort", "ModifyTime")
+	}
+
+	//更新
+	if len(updateCol) > 0 {
+		err = chartInfo.Update(updateCol)
+		if err != nil {
+			br.Msg = "移动失败"
+			br.ErrMsg = "修改失败,Err:" + err.Error()
+			return
+		}
+	}
+
+	if err != nil {
+		br.Msg = "移动失败"
+		br.ErrMsg = "修改失败,Err:" + err.Error()
+		return
+	}
+
+	//添加es数据
+	go data.EsAddOrEditChartInfo(req.ChartInfoId)
+	//修改my eta es数据
+	go data.EsAddOrEditMyChartInfoByChartInfoId(req.ChartInfoId)
+
+	//新增操作日志
+	{
+		chartLog := new(data_manage.ChartInfoLog)
+		chartLog.ChartName = chartInfo.ChartName
+		chartLog.ChartInfoId = req.ChartInfoId
+		chartLog.ChartClassifyId = chartInfo.ChartClassifyId
+		chartLog.SysUserId = sysUser.AdminId
+		chartLog.SysUserRealName = sysUser.RealName
+		chartLog.UniqueCode = chartInfo.UniqueCode
+		chartLog.CreateTime = time.Now()
+		chartLog.Content = string(c.Ctx.Input.RequestBody)
+		chartLog.Status = "移动跨品种分析图表"
+		chartLog.Method = c.Ctx.Input.URL()
+		go data_manage.AddChartInfoLog(chartLog)
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "移动成功"
+}
+
+// Refresh
+// @Title 图表刷新接口
+// @Description 图表刷新接口
+// @Param   ChartInfoId   query   int  true       "图表id"
+// @Param   UniqueCode   query   string  true       "唯一code"
+// @Success Ret=200 刷新成功
+// @router /chart_info/refresh [get]
+func (c *ChartInfoController) Refresh() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	sysUser := c.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	chartInfoId, _ := c.GetInt("ChartInfoId")
+	uniqueCode := c.GetString("UniqueCode")
+	if chartInfoId <= 0 && uniqueCode == `` {
+		br.Msg = "参数错误"
+		br.ErrMsg = "参数错误:chartInfoId:" + strconv.Itoa(chartInfoId) + ",UniqueCode:" + uniqueCode
+		return
+	}
+
+	var chartInfo *data_manage.ChartInfo
+	var err error
+	if chartInfoId > 0 {
+		chartInfo, err = data_manage.GetChartInfoById(chartInfoId)
+	} else {
+		chartInfo, err = data_manage.GetChartInfoByUniqueCode(uniqueCode)
+	}
+	if err != nil {
+		if err.Error() == utils.ErrNoRow() {
+			br.Msg = "图表已被删除,无需刷新"
+			br.ErrMsg = "获取指标信息失败,Err:" + err.Error()
+			return
+		}
+		br.Msg = "刷新失败"
+		br.ErrMsg = "获取图表信息失败,Err:" + err.Error()
+		return
+	}
+
+	var config request.ChartConfigReq
+	err = json.Unmarshal([]byte(chartInfo.ExtraConfig), &config)
+	if err != nil {
+		br.Msg = "解析跨品种分析配置失败"
+		br.ErrMsg = "解析跨品种分析配置失败,Err:" + err.Error()
+		return
+	}
+
+	// 获取关联的指标信息
+	_, _, edbInfoIdList, err := cross_variety.GetXYEdbIdList(config.TagX, config.TagY, config.VarietyList)
+	if err != nil {
+		br.Msg = "刷新失败,获取指标信息失败"
+		br.ErrMsg = "刷新失败,获取指标信息失败,Err:" + err.Error()
+		return
+	}
+
+	// 批量刷新
+	err, isAsync := data.EdbInfoRefreshAllFromBaseV3(edbInfoIdList, false, false)
+	if err != nil {
+		return
+	}
+
+	//清除图表缓存
+	{
+		key := utils.HZ_CHART_LIB_DETAIL + chartInfo.UniqueCode
+		_ = utils.Rc.Delete(key)
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "刷新成功"
+	if isAsync {
+		br.Msg = "图表关联指标较多,请10分钟后刷新页面查看最新数据"
+	}
+}
+
+// EnInfoEdit
+// @Title 编辑图表英文信息接口
+// @Description 编辑图表英文信息接口
+// @Param	request	body data_manage.EditChartEnInfoReq true "type json string"
+// @Success Ret=200 编辑成功
+// @router /chart_info/en/edit [post]
+func (c *ChartInfoController) EnInfoEdit() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	sysUser := c.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	var req request.EditChartEnInfoReq
+	err := json.Unmarshal(c.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	req.ChartNameEn = strings.Trim(req.ChartNameEn, " ")
+	if req.ChartInfoId <= 0 {
+		br.Msg = "请选择图表"
+		return
+	}
+	if req.ChartNameEn == "" {
+		br.Msg = "请输入英文图表名称"
+		return
+	}
+
+	//判断指标名称是否存在
+	chartItem, err := data_manage.GetChartInfoById(req.ChartInfoId)
+	if err != nil {
+		if err.Error() == utils.ErrNoRow() {
+			br.Msg = "图表已被删除,请刷新页面"
+			br.ErrMsg = "图表已被删除,请刷新页面"
+			return
+		}
+		br.Msg = "获取图表信息失败"
+		br.ErrMsg = "获取图表信息失败,Err:" + err.Error()
+		return
+	}
+
+	// 校验名称是否有重复
+	//{
+	//	var condition string
+	//	var pars []interface{}
+	//	condition += " AND chart_info_id <> ?  AND chart_name_en = ? AND source = ?"
+	//	pars = append(pars, req.ChartInfoId, req.ChartNameEn, utils.CHART_SOURCE_CROSS_HEDGING)
+	//	existItem, err := data_manage.GetChartInfoByCondition(condition, pars)
+	//	if err != nil {
+	//		if err.Error() != utils.ErrNoRow() {
+	//			br.Msg = "判断英文图表名称是否存在失败"
+	//			br.ErrMsg = "判断英文图表名称是否存在失败,Err:" + err.Error()
+	//			return
+	//		}
+	//	}
+	//	if err == nil && existItem.ChartInfoId > 0 {
+	//		br.Msg = existItem.ChartName + ":" + req.ChartNameEn + "图表名称已存在"
+	//		return
+	//	}
+	//}
+
+	chartItem.ChartNameEn = req.ChartNameEn
+	chartItem.ModifyTime = time.Now().Local()
+	if e := chartItem.Update([]string{"ChartNameEn", "ModifyTime"}); e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "更新图表信息失败, Err: " + e.Error()
+		return
+	}
+
+	err = cross_varietyModels.EditChartEn(chartItem, req)
+	if err != nil {
+		br.Msg = "修改失败"
+		br.ErrMsg = "更新图表英文信息失败, Err: " + err.Error()
+		return
+	}
+
+	//添加es数据
+	go data.EsAddOrEditChartInfo(chartItem.ChartInfoId)
+	//修改my eta es数据
+	go data.EsAddOrEditMyChartInfoByChartInfoId(chartItem.ChartInfoId)
+
+	//指标 修改es信息
+	//go data.AddOrEditEdbInfoToEs(edbInfo.EdbInfoId)
+
+	//新增操作日志
+	{
+		chartLog := new(data_manage.ChartInfoLog)
+		chartLog.ChartName = chartItem.ChartName
+		chartLog.ChartInfoId = req.ChartInfoId
+		chartLog.ChartClassifyId = chartItem.ChartClassifyId
+		chartLog.SysUserId = sysUser.AdminId
+		chartLog.SysUserRealName = sysUser.RealName
+		chartLog.UniqueCode = chartItem.UniqueCode
+		chartLog.CreateTime = time.Now()
+		chartLog.Content = string(c.Ctx.Input.RequestBody)
+		chartLog.Status = "编辑跨品种分析图表英文信息"
+		chartLog.Method = c.Ctx.Input.URL()
+		go data_manage.AddChartInfoLog(chartLog)
+	}
+	// 清除缓存
+	if utils.Re == nil && utils.Rc != nil {
+		_ = utils.Rc.Delete(utils.HZ_CHART_LIB_DETAIL + chartItem.UniqueCode) //图表分享链接缓存
+		_ = utils.Rc.Delete(data.GetChartInfoDataKey(req.ChartInfoId))
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "编辑成功"
+	br.IsAddLog = true
+}
+
+// DeleteChartClassify
+// @Title 删除跨品种分析分类/图表
+// @Description 删除跨品种分析分类/图表接口
+// @Param	request	body data_manage.DeleteChartClassifyReq true "type json string"
+// @Success 200 Ret=200 删除成功
+// @router /chart_info/delete [post]
+func (c *ChartInfoController) DeleteChartClassify() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+
+	sysUser := c.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+
+	var req data_manage.DeleteChartClassifyReq
+	err := json.Unmarshal(c.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	if req.ChartInfoId <= 0 {
+		br.Msg = "请选择图表"
+		br.IsSendEmail = false
+		return
+	}
+
+	resp := new(data_manage.AddChartInfoResp)
+	//删除图表
+	chartInfo, err := data_manage.GetChartInfoById(req.ChartInfoId)
+	if err != nil {
+		if err.Error() == utils.ErrNoRow() {
+			br.Msg = "图表已删除,请刷新页面"
+			br.ErrMsg = "指标不存在,Err:" + err.Error()
+			return
+		} else {
+			br.Msg = "删除失败"
+			br.ErrMsg = "删除失败,获取指标信息失败,Err:" + err.Error()
+			return
+		}
+	}
+	if chartInfo == nil {
+		br.Msg = "图表已删除,请刷新页面"
+		return
+	}
+	//图表操作权限
+	ok := data.CheckOpChartPermission(sysUser, chartInfo.SysUserId)
+	if !ok {
+		br.Msg = "没有该图表的操作权限"
+		br.ErrMsg = "没有该图表的操作权限"
+		return
+	}
+
+	myIds := make([]int, 0)
+	{
+		// 获取引用该图表的MyCharts, 用于ES删除
+		var myCond string
+		var myPars []interface{}
+		myCond += ` AND a.chart_info_id = ? `
+		myPars = append(myPars, req.ChartInfoId)
+		myCharts, e := data_manage.GetMyChartListGroupByCharyInfoIdAndAdminIdByCondition(myCond, myPars)
+		if e != nil {
+			br.Msg = "删除失败"
+			br.ErrMsg = "获取引用图表的MyChats失败, Err: " + e.Error()
+			return
+		}
+		for _, m := range myCharts {
+			myIds = append(myIds, m.MyChartId)
+		}
+	}
+	//删除图表及关联指标
+	err = data_manage.DeleteChartInfoAndData(chartInfo.ChartInfoId)
+	if err != nil {
+		br.Msg = "删除失败"
+		br.ErrMsg = "删除失败,Err:" + err.Error()
+		return
+	}
+	//删除ES
+	{
+		go data.EsDeleteChartInfo(chartInfo.ChartInfoId)
+		// 删除MY ETA 图表 es数据
+		go data.EsDeleteMyChartInfoByMyChartIds(myIds)
+	}
+
+	source := chartInfo.Source // 跨品种分析
+	var condition string
+	var pars []interface{}
+	condition += " AND chart_classify_id=? AND source = ? "
+	pars = append(pars, chartInfo.ChartClassifyId, source)
+
+	condition += " AND chart_info_id>? ORDER BY create_time ASC LIMIT 1 "
+	pars = append(pars, req.ChartInfoId)
+
+	nextItem, err := data_manage.GetChartInfoByCondition(condition, pars)
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		br.Msg = "删除失败"
+		br.ErrMsg = "获取下一级图库信息失败,Err:" + err.Error()
+		return
+	}
+
+	if nextItem != nil {
+		resp.UniqueCode = nextItem.UniqueCode
+		resp.ChartInfoId = nextItem.ChartInfoId
+	} else {
+		var tmpCondition string
+		var tmpPars []interface{}
+
+		tmpCondition += " AND level=1 "
+		//pars = append(pars, chartInfo.ChartClassifyId)
+
+		tmpCondition += " AND chart_classify_id>? ORDER BY chart_classify_id ASC LIMIT 1 "
+		tmpPars = append(tmpPars, chartInfo.ChartClassifyId)
+
+		classifyItem, err := data_manage.GetChartClassifyByCondition(tmpCondition, tmpPars)
+		if err != nil && err.Error() != utils.ErrNoRow() {
+			br.Msg = "删除失败"
+			br.ErrMsg = "获取下一级图库分类信息失败,Err:" + err.Error()
+			return
+		}
+		if classifyItem != nil {
+			nextItem, err = data_manage.GetNextChartInfo(chartInfo.ChartClassifyId)
+			if err != nil && err.Error() != utils.ErrNoRow() {
+				br.Msg = "删除失败"
+				br.ErrMsg = "获取下一级图库信息失败,Err:" + err.Error()
+				return
+			}
+			if nextItem != nil {
+				resp.UniqueCode = nextItem.UniqueCode
+				resp.ChartInfoId = nextItem.ChartInfoId
+			}
+		}
+	}
+	//新增操作日志
+	{
+		chartLog := new(data_manage.ChartInfoLog)
+		chartLog.ChartName = chartInfo.ChartName
+		chartLog.ChartInfoId = req.ChartInfoId
+		chartLog.ChartClassifyId = chartInfo.ChartClassifyId
+		chartLog.SysUserId = sysUser.AdminId
+		chartLog.SysUserRealName = sysUser.RealName
+		chartLog.UniqueCode = chartInfo.UniqueCode
+		chartLog.CreateTime = time.Now()
+		chartLog.Content = string(c.Ctx.Input.RequestBody)
+		chartLog.Status = "删除图表"
+		chartLog.Method = c.Ctx.Input.URI()
+		go data_manage.AddChartInfoLog(chartLog)
+	}
+
+	br.Ret = 200
+	br.Msg = "删除成功"
+	br.Success = true
+	br.Data = resp
+	br.IsAddLog = true
+}
+
+// SearchByEs
+// @Title 图表模糊搜索(从es获取)
+// @Description  图表模糊搜索(从es获取)
+// @Param   Keyword   query   string  true       "图表名称"
+// @Param   IsShowMe   query   bool  true       "是否只看我的,true、false"
+// @Param   Source   query   int  true       "来源,3:拟合方程,4:滚动拟合方程,默认0:全部"
+// @Success 200 {object} data_manage.ChartInfo
+// @router /chart_info/search_by_es [get]
+func (c *ChartInfoController) SearchByEs() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+
+	sysUser := c.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	pageSize, _ := c.GetInt("PageSize")
+	currentIndex, _ := c.GetInt("CurrentIndex")
+
+	var startSize int
+	if pageSize <= 0 {
+		pageSize = utils.PageSize20
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	startSize = paging.StartIndex(currentIndex, pageSize)
+
+	keyword := c.GetString("Keyword")
+
+	//只看我的
+	isShowMe, _ := c.GetBool("IsShowMe")
+	showSysId := 0
+	if isShowMe {
+		showSysId = sysUser.AdminId
+	}
+
+	sourceList := []int{utils.CHART_SOURCE_CROSS_HEDGING}
+
+	var searchList []*data_manage.ChartInfo
+	var total int64
+	var err error
+
+	// 获取当前账号的不可见指标
+	noPermissionChartIdList := make([]int, 0)
+	{
+		obj := data_manage.EdbInfoNoPermissionAdmin{}
+		confList, err := obj.GetAllChartListByAdminId(c.SysUser.AdminId)
+		if err != nil && err.Error() != utils.ErrNoRow() {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取不可见指标配置数据失败,Err:" + err.Error()
+			return
+		}
+		for _, v := range confList {
+			noPermissionChartIdList = append(noPermissionChartIdList, v.ChartInfoId)
+		}
+	}
+
+	if keyword != "" {
+		searchList, total, err = data.EsSearchChartInfo(keyword, showSysId, sourceList, noPermissionChartIdList, startSize, pageSize)
+	} else {
+		total, searchList, err = data_manage.ChartInfoSearchByEmptyKeyWord(showSysId, sourceList, noPermissionChartIdList, startSize, pageSize)
+		if err != nil && err.Error() != utils.ErrNoRow() {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取图表信息失败,Err:" + err.Error()
+			return
+		}
+	}
+
+	finalList := make([]*data_manage.ChartInfoMore, 0)
+	if len(searchList) > 0 {
+		chartInfoIds := ""
+		chartEdbMap := make(map[int][]*data_manage.ChartEdbInfoMapping)
+		for _, v := range searchList {
+			chartInfoIds += strconv.Itoa(v.ChartInfoId) + ","
+		}
+		if chartInfoIds != "" {
+			chartInfoIds = strings.Trim(chartInfoIds, ",")
+			//判断是否需要展示英文标识
+			edbList, e := data_manage.GetChartEdbMappingListByChartInfoIds(chartInfoIds)
+			if e != nil {
+				br.Msg = "获取失败"
+				br.ErrMsg = "获取图表,指标信息失败,Err:" + e.Error()
+				return
+			}
+			for _, v := range edbList {
+				chartEdbMap[v.ChartInfoId] = append(chartEdbMap[v.ChartInfoId], v)
+			}
+		}
+
+		for _, v := range searchList {
+			tmp := new(data_manage.ChartInfoMore)
+			tmp.ChartInfo = *v
+			//判断是否需要展示英文标识
+			if _, ok := chartEdbMap[v.ChartInfoId]; ok {
+				tmp.IsEnChart = data.CheckIsEnChart(v.ChartNameEn, []*data_manage.ChartEdbInfoMapping{}, v.Source, v.ChartType)
+			}
+			finalList = append(finalList, tmp)
+		}
+	}
+	//新增搜索词记录
+	{
+		searchKeyword := new(data_manage.SearchKeyword)
+		searchKeyword.KeyWord = keyword
+		searchKeyword.CreateTime = time.Now()
+		go data_manage.AddSearchKeyword(searchKeyword)
+	}
+
+	page := paging.GetPaging(currentIndex, pageSize, int(total))
+	resp := data_manage.ChartInfoListByEsResp{
+		Paging: page,
+		List:   finalList,
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+// GetChartInfoDetailFromUniqueCode 根据编码获取图表详情
+func GetChartInfoDetailFromUniqueCode(chartInfo *data_manage.ChartInfoView, isCache bool, sysUser *system.Admin) (resp *data_manage.ChartInfoDetailFromUniqueCodeResp, isOk bool, msg, errMsg string) {
+	resp = new(data_manage.ChartInfoDetailFromUniqueCodeResp)
+
+	adminId := sysUser.AdminId
+
+	//判断是否存在缓存,如果存在缓存,那么直接从缓存中获取
+	key := data.GetChartInfoDataKey(chartInfo.ChartInfoId)
+	if utils.Re == nil && isCache {
+		if utils.Re == nil && utils.Rc.IsExist(key) {
+			if chartData, err1 := utils.Rc.RedisBytes(key); err1 == nil {
+				err := json.Unmarshal(chartData, &resp)
+				if err == nil && resp != nil {
+					// 这里跟当前用户相关的信息重新查询写入resp, 不使用缓存中的
+					var myCond string
+					var myPars []interface{}
+					myCond += ` AND a.admin_id=? `
+					myPars = append(myPars, adminId)
+					myCond += ` AND a.chart_info_id=? `
+					myPars = append(myPars, chartInfo.ChartInfoId)
+					myList, err := data_manage.GetMyChartByCondition(myCond, myPars)
+					if err != nil && err.Error() != utils.ErrNoRow() {
+						msg = "获取失败"
+						errMsg = "获取我的图表信息失败,GetMyChartByCondition,Err:" + err.Error()
+						return
+					}
+					resp.ChartInfo.IsAdd = false
+					resp.ChartInfo.MyChartId = 0
+					resp.ChartInfo.MyChartClassifyId = ""
+					if myList != nil && len(myList) > 0 {
+						resp.ChartInfo.IsAdd = true
+						resp.ChartInfo.MyChartId = myList[0].MyChartId
+						resp.ChartInfo.MyChartClassifyId = myList[0].MyChartClassifyId
+					}
+
+					isOk = true
+					fmt.Println("source redis")
+					return
+				}
+			}
+		}
+	}
+
+	chartInfoId := chartInfo.ChartInfoId
+
+	if chartInfo.ExtraConfig == `` {
+		msg = "图表配置信息异常"
+		errMsg = "图表配置信息异常"
+		return
+	}
+	var config request.ChartConfigReq
+	err := json.Unmarshal([]byte(chartInfo.ExtraConfig), &config)
+	if err != nil {
+		msg = "解析跨品种分析配置失败"
+		errMsg = "解析跨品种分析配置失败,Err:" + err.Error()
+		return
+	}
+	// 获取图表x轴y轴
+	edbList, dataResp, err, msg, _ := cross_variety.GetChartData(0, config)
+	if err != nil {
+		errMsg = "获取图表,指标信息失败,Err:" + err.Error()
+		return
+	}
+	if chartInfoId > 0 && chartInfo != nil {
+		//判断是否加入我的图库
+		{
+			var myChartCondition string
+			var myChartPars []interface{}
+			myChartCondition += ` AND a.admin_id=? `
+			myChartPars = append(myChartPars, sysUser.AdminId)
+			myChartCondition += ` AND a.chart_info_id=? `
+			myChartPars = append(myChartPars, chartInfo.ChartInfoId)
+
+			myChartList, err := data_manage.GetMyChartByCondition(myChartCondition, myChartPars)
+			if err != nil && err.Error() != utils.ErrNoRow() {
+				msg = "获取失败"
+				errMsg = "获取我的图表信息失败,GetMyChartByCondition,Err:" + err.Error()
+				return
+			}
+			if myChartList != nil && len(myChartList) > 0 {
+				chartInfo.IsAdd = true
+				chartInfo.MyChartId = myChartList[0].MyChartId
+				chartInfo.MyChartClassifyId = myChartList[0].MyChartClassifyId
+			}
+		}
+	}
+
+	//图表操作权限
+	chartInfo.IsEdit = data.CheckOpChartPermission(sysUser, chartInfo.SysUserId)
+	//判断是否需要展示英文标识
+	//chartInfo.IsEnChart = data.CheckIsEnChart(chartInfo.ChartNameEn, edbList[0:1], chartInfo.Source, chartInfo.ChartType)
+	//chartInfo.UnitEn = edbInfoMappingA.UnitEn
+
+	//isSaveAs := true
+	// 另存为
+	chartInfo.Button = data_manage.ChartViewButton{
+		IsEdit:    chartInfo.IsEdit,
+		IsEnChart: chartInfo.IsEnChart,
+		IsAdd:     chartInfo.IsAdd,
+		IsCopy:    true,
+		IsSetName: chartInfo.IsSetName,
+	}
+
+	resp.ChartInfo = chartInfo
+	resp.DataResp = dataResp
+	resp.EdbInfoList = edbList
+	resp.Status = true
+
+	// 将数据加入缓存
+	if utils.Re == nil {
+		d, _ := json.Marshal(resp)
+		_ = utils.Rc.Put(key, d, 2*time.Hour)
+	}
+	isOk = true
+	return
+}

+ 422 - 0
controllers/data_manage/cross_variety/classify.go

@@ -0,0 +1,422 @@
+package cross_variety
+
+import (
+	"encoding/json"
+	"eta/eta_mobile/controllers"
+	"eta/eta_mobile/models"
+	"eta/eta_mobile/models/data_manage"
+	"eta/eta_mobile/services/data"
+	"eta/eta_mobile/utils"
+	"time"
+)
+
+// ClassifyController
+// @Description: 跨品种分析分类
+type ClassifyController struct {
+	controllers.BaseAuthController
+}
+
+// List
+// @Title 跨品种分析分类列表
+// @Description 跨品种分析分类列表接口
+// @Param   IsShowMe   query   bool  true       "是否只看我的,true、false"
+// @Param   Source   query   int  true       "图表类型,3:跨品种分析,4:滚动跨品种分析"
+// @Success 200 {object} data_manage.ChartClassifyListResp
+// @router /classify/list [get]
+func (c *ClassifyController) List() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	resp := new(data_manage.ChartClassifyListResp)
+
+	// 获取当前账号的不可见指标
+	noPermissionChartIdMap := make(map[int]bool)
+	{
+		obj := data_manage.EdbInfoNoPermissionAdmin{}
+		confList, err := obj.GetAllChartListByAdminId(c.SysUser.AdminId)
+		if err != nil && err.Error() != utils.ErrNoRow() {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取不可见指标配置数据失败,Err:" + err.Error()
+			return
+		}
+		for _, v := range confList {
+			noPermissionChartIdMap[v.ChartInfoId] = true
+		}
+	}
+
+	isShowMe, _ := c.GetBool("IsShowMe")
+
+	source, _ := c.GetInt("Source")
+	if source <= 0 {
+		source = utils.CHART_SOURCE_CROSS_HEDGING
+	}
+
+	rootList, err := data_manage.GetChartClassifyByParentId(0, utils.CHART_SOURCE_CROSS_HEDGING)
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+		return
+	}
+
+	allChartInfo, err := data_manage.GetChartInfoAll([]int{source})
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取图表信息失败,Err:" + err.Error()
+		return
+	}
+
+	chartInfoMap := make(map[int][]*data_manage.ChartClassifyItems)
+	for _, v := range allChartInfo {
+		if !isShowMe {
+			chartInfoMap[v.ChartClassifyId] = append(chartInfoMap[v.ChartClassifyId], v)
+			continue
+		}
+		if v.SysUserId != c.SysUser.AdminId {
+			continue
+		}
+		chartInfoMap[v.ChartClassifyId] = append(chartInfoMap[v.ChartClassifyId], v)
+	}
+	rootChildMap := make(map[int][]*data_manage.ChartClassifyItems)
+
+	// 移除没有图表的分类
+	allNodes := make([]*data_manage.ChartClassifyItems, 0)
+	for _, v := range rootList {
+
+		rootChildMap[v.ParentId] = append(rootChildMap[v.ParentId], v)
+		if existItems, ok := chartInfoMap[v.ChartClassifyId]; ok {
+			v.Children = existItems
+			allNodes = append(allNodes, v)
+		}
+	}
+
+	// 移除没有权限的图表
+	allNodes = data.HandleNoPermissionChart(allNodes, noPermissionChartIdMap)
+	resp.AllNodes = allNodes
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+// EditChartClassify
+// @Title 修改跨品种分析图表分类
+// @Description 修改跨品种分析图表分类接口
+// @Param	request	body data_manage.EditChartClassifyReq true "type json string"
+// @Success 200 Ret=200 修改成功
+// @router /classify/edit [post]
+func (c *ClassifyController) EditChartClassify() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	var req data_manage.EditChartClassifyReq
+	err := json.Unmarshal(c.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.ChartClassifyName == "" {
+		br.Msg = "请输入分类名称"
+		br.IsSendEmail = false
+		return
+	}
+
+	if req.ChartClassifyId <= 0 {
+		br.Msg = "参数错误"
+		br.IsSendEmail = false
+		return
+	}
+
+	item, err := data_manage.GetChartClassifyById(req.ChartClassifyId)
+	if err != nil {
+		br.Msg = "保存失败"
+		br.Msg = "获取分类信息失败,Err:" + err.Error()
+		return
+	}
+
+	source := utils.CHART_SOURCE_CROSS_HEDGING
+	if item.ChartClassifyName != req.ChartClassifyName {
+		//count, err := data_manage.GetChartClassifyCount(req.ChartClassifyName, item.ParentId, source)
+		//if err != nil {
+		//	br.Msg = "判断名称是否已存在失败"
+		//	br.ErrMsg = "判断名称是否已存在失败,Err:" + err.Error()
+		//	return
+		//}
+		//if count > 0 {
+		//	br.Msg = "分类名称已存在,请重新输入"
+		//	br.IsSendEmail = false
+		//	return
+		//}
+
+		err = data_manage.EditChartClassify(req.ChartClassifyId, source, req.ChartClassifyName)
+		if err != nil {
+			br.Msg = "保存失败"
+			br.ErrMsg = "保存失败,Err:" + err.Error()
+			return
+		}
+	}
+	br.Ret = 200
+	br.Msg = "修改成功"
+	br.Success = true
+	br.IsAddLog = true
+}
+
+// DeleteChartClassifyCheck
+// @Title 删除图表检测接口
+// @Description 删除图表检测接口
+// @Param	request	body data_manage.ChartClassifyDeleteCheckResp true "type json string"
+// @Success 200 Ret=200 检测成功
+// @router /classify/delete/check [post]
+func (c *ClassifyController) DeleteChartClassifyCheck() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	var req data_manage.ChartClassifyDeleteCheckReq
+	err := json.Unmarshal(c.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	if req.ChartClassifyId < 0 && req.ChartInfoId <= 0 {
+		br.Msg = "参数错误"
+		br.IsSendEmail = false
+		return
+	}
+	var deleteStatus int
+	var tipsMsg string
+	//删除分类
+	if req.ChartClassifyId > 0 && req.ChartInfoId == 0 {
+		//判断跨品种分析图表分类下,是否含有图表
+		count, err := data_manage.GetChartInfoCountByClassifyId(req.ChartClassifyId)
+		if err != nil {
+			br.Msg = "删除失败"
+			br.ErrMsg = "分类下是否含有图表失败,Err:" + err.Error()
+			return
+		}
+
+		if count > 0 {
+			deleteStatus = 1
+			tipsMsg = "该分类下关联图表不可删除"
+		}
+	}
+
+	if deleteStatus != 1 && req.ChartInfoId == 0 {
+		classifyCount, err := data_manage.GetChartClassifyCountByClassifyId(req.ChartClassifyId)
+		if err != nil && err.Error() != utils.ErrNoRow() {
+			br.Msg = "删除失败"
+			br.ErrMsg = "分类下是否含有图表失败,Err:" + err.Error()
+			return
+		}
+		if classifyCount > 0 {
+			deleteStatus = 2
+			tipsMsg = "确认删除当前目录及包含的子目录吗"
+		}
+	}
+	if deleteStatus == 0 {
+		tipsMsg = "可删除,进行删除操作"
+	}
+
+	resp := new(data_manage.ChartClassifyDeleteCheckResp)
+	resp.DeleteStatus = deleteStatus
+	resp.TipsMsg = tipsMsg
+	br.Ret = 200
+	br.Msg = "检测成功"
+	br.Success = true
+	br.Data = resp
+}
+
+// DeleteChartClassify
+// @Title 删除跨品种分析图表分类/图表
+// @Description 删除跨品种分析图表分类/图表接口
+// @Param	request	body data_manage.DeleteChartClassifyReq true "type json string"
+// @Success 200 Ret=200 删除成功
+// @router /classify/delete [post]
+func (c *ClassifyController) DeleteChartClassify() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+
+	sysUser := c.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+
+	var req data_manage.DeleteChartClassifyReq
+	err := json.Unmarshal(c.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	if req.ChartClassifyId < 0 && req.ChartInfoId <= 0 {
+		br.Msg = "参数错误"
+		br.IsSendEmail = false
+		return
+	}
+
+	//删除分类
+	if req.ChartClassifyId > 0 && req.ChartInfoId == 0 {
+		//判断是否含有指标
+		count, err := data_manage.GetChartInfoCountByClassifyId(req.ChartClassifyId)
+		if err != nil && err.Error() != utils.ErrNoRow() {
+			br.Msg = "删除失败"
+			br.ErrMsg = "判断名称是否已存在失败,Err:" + err.Error()
+			return
+		}
+
+		if count > 0 {
+			br.Msg = "该目录下存在关联指标,不可删除"
+			br.IsSendEmail = false
+			return
+		}
+
+		err = data_manage.DeleteChartClassify(req.ChartClassifyId)
+		if err != nil {
+			br.Msg = "删除失败"
+			br.ErrMsg = "删除失败,Err:" + err.Error()
+			return
+		}
+	}
+	resp := new(data_manage.AddChartInfoResp)
+	//删除图表
+	if req.ChartInfoId > 0 {
+		chartInfo, err := data_manage.GetChartInfoById(req.ChartInfoId)
+		if err != nil {
+			if err.Error() == utils.ErrNoRow() {
+				br.Msg = "图表已删除,请刷新页面"
+				br.ErrMsg = "指标不存在,Err:" + err.Error()
+				return
+			} else {
+				br.Msg = "删除失败"
+				br.ErrMsg = "删除失败,获取指标信息失败,Err:" + err.Error()
+				return
+			}
+		}
+		if chartInfo == nil {
+			br.Msg = "图表已删除,请刷新页面"
+			return
+		}
+		//图表操作权限
+		ok := data.CheckOpChartPermission(sysUser, chartInfo.SysUserId)
+		if !ok {
+			br.Msg = "没有该图表的操作权限"
+			br.ErrMsg = "没有该图表的操作权限"
+			return
+		}
+
+		// 获取引用该图表的MyCharts, 用于ES删除
+		var myCond string
+		var myPars []interface{}
+		myCond += ` AND a.chart_info_id = ? `
+		myPars = append(myPars, chartInfo.ChartInfoId)
+		myCharts, e := data_manage.GetMyChartListGroupByCharyInfoIdAndAdminIdByCondition(myCond, myPars)
+		if e != nil {
+			br.Msg = "删除失败"
+			br.ErrMsg = "获取引用图表的MyChats失败, Err: " + e.Error()
+			return
+		}
+		myIds := make([]int, 0)
+		for _, m := range myCharts {
+			myIds = append(myIds, m.MyChartId)
+		}
+
+		source := chartInfo.Source // 跨品种分析图表(滚动跨品种分析)
+		//删除图表及关联指标
+		err = data_manage.DeleteChartInfoAndData(chartInfo.ChartInfoId)
+		if err != nil {
+			br.Msg = "删除失败"
+			br.ErrMsg = "删除失败,Err:" + err.Error()
+			return
+		}
+		//删除ES
+		{
+			go data.EsDeleteChartInfo(chartInfo.ChartInfoId)
+			// 删除MY ETA 图表 es数据
+			//go data.EsDeleteMyChartInfoByChartInfoId(chartInfo.ChartInfoId)
+			go data.EsDeleteMyChartInfoByMyChartIds(myIds)
+		}
+
+		var condition string
+		var pars []interface{}
+		condition += " AND chart_classify_id=? AND source = ? "
+		pars = append(pars, chartInfo.ChartClassifyId, source)
+
+		condition += " AND chart_info_id>? ORDER BY create_time ASC LIMIT 1 "
+		pars = append(pars, req.ChartInfoId)
+
+		nextItem, err := data_manage.GetChartInfoByCondition(condition, pars)
+		if err != nil && err.Error() != utils.ErrNoRow() {
+			br.Msg = "删除失败"
+			br.ErrMsg = "获取下一级图库信息失败,Err:" + err.Error()
+			return
+		}
+
+		if nextItem != nil {
+			resp.UniqueCode = nextItem.UniqueCode
+			resp.ChartInfoId = nextItem.ChartInfoId
+		} else {
+			var condition string
+			var pars []interface{}
+
+			condition += " AND level=1 "
+			//pars = append(pars, chartInfo.ChartClassifyId)
+
+			condition += " AND chart_classify_id>? ORDER BY chart_classify_id ASC LIMIT 1 "
+			pars = append(pars, chartInfo.ChartClassifyId)
+
+			classifyItem, err := data_manage.GetChartClassifyByCondition(condition, pars)
+			if err != nil && err.Error() != utils.ErrNoRow() {
+				br.Msg = "删除失败"
+				br.ErrMsg = "获取下一级图库分类信息失败,Err:" + err.Error()
+				return
+			}
+			if classifyItem != nil {
+				nextItem, err = data_manage.GetNextChartInfo(chartInfo.ChartClassifyId)
+				if err != nil && err.Error() != utils.ErrNoRow() {
+					br.Msg = "删除失败"
+					br.ErrMsg = "获取下一级图库信息失败,Err:" + err.Error()
+					return
+				}
+				if nextItem != nil {
+					resp.UniqueCode = nextItem.UniqueCode
+					resp.ChartInfoId = nextItem.ChartInfoId
+				}
+			}
+		}
+		//新增操作日志
+		{
+			chartLog := new(data_manage.ChartInfoLog)
+			chartLog.ChartName = chartInfo.ChartName
+			chartLog.ChartInfoId = req.ChartInfoId
+			chartLog.ChartClassifyId = chartInfo.ChartClassifyId
+			chartLog.SysUserId = sysUser.AdminId
+			chartLog.SysUserRealName = sysUser.RealName
+			chartLog.UniqueCode = chartInfo.UniqueCode
+			chartLog.CreateTime = time.Now()
+			chartLog.Content = string(c.Ctx.Input.RequestBody)
+			chartLog.Status = "删除图表"
+			chartLog.Method = c.Ctx.Input.URI()
+			go data_manage.AddChartInfoLog(chartLog)
+		}
+	}
+	br.Ret = 200
+	br.Msg = "删除成功"
+	br.Success = true
+	br.Data = resp
+	br.IsAddLog = true
+}

+ 404 - 0
controllers/data_manage/cross_variety/tag.go

@@ -0,0 +1,404 @@
+package cross_variety
+
+import (
+	"encoding/json"
+	"eta/eta_mobile/controllers"
+	"eta/eta_mobile/models"
+	"eta/eta_mobile/models/data_manage/cross_variety"
+	"eta/eta_mobile/models/data_manage/cross_variety/request"
+	"eta/eta_mobile/models/data_manage/cross_variety/response"
+	"eta/eta_mobile/utils"
+	"github.com/rdlucklib/rdluck_tools/paging"
+	"time"
+)
+
+// TagController
+// @Description: 标签列表
+type TagController struct {
+	controllers.BaseAuthController
+}
+
+// Add
+// @Title 新增标签
+// @Description 新增标签接口
+// @Param	request	body request.AddTagReq true "type json string"
+// @Success 200 Ret=200 添加成功
+// @router /tag/add [post]
+func (c *TagController) Add() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	var req request.AddTagReq
+	err := json.Unmarshal(c.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.TagName == "" {
+		br.Msg = "请输入标签名称"
+		br.IsSendEmail = false
+		return
+	}
+	TagName := utils.TrimStr(req.TagName)
+	item, err := cross_variety.GetTagByName(TagName)
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		br.Msg = "添加失败"
+		br.ErrMsg = "添加失败,Err:" + err.Error()
+		return
+	}
+	if item != nil {
+		br.Msg = "添加失败,标签名称不能重复"
+		br.IsSendEmail = false
+		return
+	}
+
+	tag := &cross_variety.ChartTag{
+		ChartTagId:      0,
+		ChartTagName:    TagName,
+		SysUserId:       c.SysUser.AdminId,
+		SysUserRealName: c.SysUser.RealName,
+		ModifyTime:      time.Now(),
+		CreateTime:      time.Now(),
+	}
+	err = cross_variety.AddTag(tag)
+	if err != nil {
+		br.Msg = "添加标签失败"
+		br.ErrMsg = "添加标签失败,Err:" + err.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Msg = "添加成功"
+	br.IsAddLog = true
+	br.Success = true
+}
+
+// Edit
+// @Title 编辑标签接口
+// @Description 编辑标签接口
+// @Param	request	body request.EditTagReq true "type json string"
+// @Success 200 Ret=200 修改成功
+// @router /tag/edit [post]
+func (c *TagController) Edit() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	var req request.EditTagReq
+	err := json.Unmarshal(c.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.ChartTagId <= 0 {
+		br.Msg = "请选择标签"
+		br.IsSendEmail = false
+		return
+	}
+	if req.TagName == "" {
+		br.Msg = "请输入标签名称"
+		br.IsSendEmail = false
+		return
+	}
+	TagName := utils.TrimStr(req.TagName)
+
+	item, err := cross_variety.GetTagByName(TagName)
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		br.Msg = "添加失败"
+		br.ErrMsg = "添加失败,Err:" + err.Error()
+		return
+	}
+	if item != nil && item.ChartTagId != req.ChartTagId {
+		br.Msg = "添加失败,标签名称不能重复"
+		br.IsSendEmail = false
+		return
+	}
+
+	// 获取标签详情
+	varietyInfo, err := cross_variety.GetTagById(req.ChartTagId)
+	if err != nil {
+		br.Msg = "查询标签失败"
+		br.ErrMsg = "查询标签失败;ERR:" + err.Error()
+		return
+	}
+
+	// 编辑
+	varietyInfo.ChartTagName = TagName
+	varietyInfo.ModifyTime = time.Now()
+	err = varietyInfo.Update([]string{"ChartTagName", "ModifyTime"})
+	if err != nil {
+		br.Msg = "修改标签失败"
+		br.ErrMsg = "修改标签失败,Err:" + err.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Msg = "修改成功"
+	br.IsAddLog = true
+	br.Success = true
+}
+
+// DeleteCheck
+// @Title 删除标签检测接口
+// @Description 删除标签检测接口
+// @Param	request	body request.DelTagReq true "type json string"
+// @Success 200 Ret=200 检测成功
+// @router /tag/delete/check [post]
+func (c *TagController) DeleteCheck() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	var req request.DelTagReq
+	err := json.Unmarshal(c.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	if req.ChartTagId <= 0 {
+		br.Msg = "请选择标签"
+		br.IsSendEmail = false
+		return
+	}
+	var deleteStatus int
+	var tipsMsg string
+
+	// 获取该标签关联的图表数
+	count, err := cross_variety.GetCountChartByTagId(req.ChartTagId)
+	if err != nil {
+		br.Msg = "检测异常"
+		br.ErrMsg = "检测异常,err:" + err.Error()
+		br.IsSendEmail = false
+		return
+	}
+	if count > 0 {
+		deleteStatus = 1
+		tipsMsg = "已关联图表的品种,不允许删除!"
+	}
+
+	if deleteStatus == 0 {
+		tipsMsg = "可删除,进行删除操作"
+	}
+
+	resp := response.TagDeleteCheckResp{
+		DeleteStatus: deleteStatus,
+		TipsMsg:      tipsMsg,
+	}
+	br.Ret = 200
+	br.Msg = "检测成功"
+	br.Success = true
+	br.Data = resp
+}
+
+// Delete
+// @Title 删除标签
+// @Description 删除标签接口
+// @Param	request	body request.DeleteChartClassifyReq true "type json string"
+// @Success 200 Ret=200 删除成功
+// @router /tag/delete [post]
+func (c *TagController) Delete() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	var req request.DelTagReq
+	err := json.Unmarshal(c.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	if req.ChartTagId <= 0 {
+		br.Msg = "请选择标签"
+		br.IsSendEmail = false
+		return
+	}
+
+	// 获取该标签关联的图表数
+	count, err := cross_variety.GetCountChartByTagId(req.ChartTagId)
+	if err != nil {
+		br.Msg = "检测异常"
+		br.ErrMsg = "检测异常,err:" + err.Error()
+		br.IsSendEmail = false
+		return
+	}
+	if count > 0 {
+		br.Msg = "已关联图表的品种,不允许删除!"
+		br.ErrMsg = "已关联图表的品种,不允许删除!"
+		br.IsSendEmail = false
+		return
+	}
+
+	varietyInfo, err := cross_variety.GetTagById(req.ChartTagId)
+	if err != nil {
+		if err.Error() == utils.ErrNoRow() {
+			br.Msg = "该标签不存在或已删除"
+			br.IsSendEmail = false
+		} else {
+			br.Msg = "删除失败"
+			br.ErrMsg = "查找标签失败,ERR:" + err.Error()
+		}
+		return
+	}
+	err = varietyInfo.Delete()
+	if err != nil {
+		br.Msg = "删除失败"
+		br.ErrMsg = "删除标签失败,ERR:" + err.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Msg = "删除成功"
+	br.Success = true
+	br.IsAddLog = true
+}
+
+// List
+// @Title 获取标签中的指标与品种的映射关系
+// @Description 获取标签中的指标与品种的映射关系
+// @Param   ChartTagId   query   int  true       "标签id"
+// @Success 200 Ret=200 保存成功
+// @router /tag/list [get]
+func (c *TagController) List() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	// 获取数据
+	list, err := cross_variety.GetTagItemList()
+	if err != nil {
+		br.Msg = "获取标签失败"
+		br.ErrMsg = "获取标签失败,ERR:" + err.Error()
+		return
+	}
+	dataCount := len(list)
+	page := paging.GetPaging(1, dataCount, dataCount)
+
+	// 获取标签绑定的品种数量
+	tagTotalList, err := cross_variety.GetCountChartTagVarietyItemListByTag()
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取标签绑定的品种数量失败,ERR:" + err.Error()
+		return
+	}
+
+	tagTotalMap := make(map[int]int)
+	for _, v := range tagTotalList {
+		tagTotalMap[v.ChartTagId] = v.Total
+	}
+
+	for k, v := range list {
+		list[k].VarietyTotal = tagTotalMap[v.ChartTagId]
+	}
+
+	resp := response.TagListResp{
+		List:   list,
+		Paging: page,
+	}
+
+	br.Ret = 200
+	br.Msg = "获取成功"
+	br.Success = true
+	br.Data = resp
+}
+
+// VarietyEdbList
+// @Title 获取标签中的指标与品种的映射关系
+// @Description 获取标签中的指标与品种的映射关系
+// @Param   ChartTagId   query   int  true       "标签id"
+// @Success 200 Ret=200 保存成功
+// @router /tag/variety_edb/list [get]
+func (c *TagController) VarietyEdbList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+
+	chartTagId, _ := c.GetInt("ChartTagId")
+	if chartTagId <= 0 {
+		br.Msg = "请选择标签"
+		br.IsSendEmail = false
+		return
+	}
+
+	// 获取数据
+	list, err := cross_variety.GetChartTagVarietyItemListByTag(chartTagId)
+	if err != nil {
+		br.Msg = "保存失败"
+		br.ErrMsg = "保存失败,ERR:" + err.Error()
+		return
+	}
+	dataCount := len(list)
+	page := paging.GetPaging(1, dataCount, dataCount)
+
+	resp := response.VarietyEdbListResp{
+		List:   list,
+		Paging: page,
+	}
+
+	br.Ret = 200
+	br.Msg = "保存成功"
+	br.Success = true
+	br.Data = resp
+}
+
+// SaveVarietyEdb
+// @Title 配置标签中的指标与品种的映射关系
+// @Description 配置标签中的指标与品种的映射关系
+// @Param	request	body request.SaveTagVarietyEdbReq true "type json string"
+// @Success 200 Ret=200 保存成功
+// @router /tag/variety_edb/save [post]
+func (c *TagController) SaveVarietyEdb() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	var req request.SaveTagVarietyEdbReq
+	err := json.Unmarshal(c.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	if req.ChartTagId <= 0 {
+		br.Msg = "请选择标签"
+		br.IsSendEmail = false
+		return
+	}
+
+	// 过滤未配置的品种
+	varietyEdbList := make([]request.VarietyEdbReq, 0)
+	for _, v := range req.VarietyEdb {
+		if v.EdbInfoId <= 0 {
+			continue
+		}
+		varietyEdbList = append(varietyEdbList, v)
+	}
+
+	// 保存配置
+	err = cross_variety.SaveVarietyEdb(req.ChartTagId, varietyEdbList, c.SysUser.AdminId, c.SysUser.RealName)
+	if err != nil {
+		br.Msg = "保存失败"
+		br.ErrMsg = "保存失败,ERR:" + err.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Msg = "保存成功"
+	br.Success = true
+	br.IsAddLog = true
+}

+ 295 - 0
controllers/data_manage/cross_variety/variety.go

@@ -0,0 +1,295 @@
+package cross_variety
+
+import (
+	"encoding/json"
+	"eta/eta_mobile/controllers"
+	"eta/eta_mobile/models"
+	"eta/eta_mobile/models/data_manage/cross_variety"
+	"eta/eta_mobile/models/data_manage/cross_variety/request"
+	"eta/eta_mobile/models/data_manage/cross_variety/response"
+	"eta/eta_mobile/utils"
+	"github.com/rdlucklib/rdluck_tools/paging"
+	"time"
+)
+
+// VarietyController
+// @Description: 品种列表
+type VarietyController struct {
+	controllers.BaseAuthController
+}
+
+// Add
+// @Title 新增品种
+// @Description 新增品种接口
+// @Param	request	body request.AddVarietyReq true "type json string"
+// @Success 200 Ret=200 添加成功
+// @router /variety/add [post]
+func (c *VarietyController) Add() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	var req request.AddVarietyReq
+	err := json.Unmarshal(c.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.VarietyName == "" {
+		br.Msg = "请输入品种名称"
+		br.IsSendEmail = false
+		return
+	}
+	varietyName := utils.TrimStr(req.VarietyName)
+	item, err := cross_variety.GetVarietyByName(varietyName)
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		br.Msg = "添加失败"
+		br.ErrMsg = "添加失败,Err:" + err.Error()
+		return
+	}
+	if item != nil {
+		br.Msg = "添加失败,品种名称不能重复"
+		br.IsSendEmail = false
+		return
+	}
+
+	variety := &cross_variety.ChartVariety{
+		ChartVarietyId:   0,
+		ChartVarietyName: varietyName,
+		SysUserId:        c.SysUser.AdminId,
+		SysUserRealName:  c.SysUser.RealName,
+		ModifyTime:       time.Now(),
+		CreateTime:       time.Now(),
+	}
+	err = cross_variety.AddVariety(variety)
+	if err != nil {
+		br.Msg = "添加品种失败"
+		br.ErrMsg = "添加品种失败,Err:" + err.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Msg = "添加成功"
+	br.IsAddLog = true
+	br.Success = true
+}
+
+// Edit
+// @Title 编辑品种接口
+// @Description 编辑品种接口
+// @Param	request	body request.EditVarietyReq true "type json string"
+// @Success 200 Ret=200 修改成功
+// @router /variety/edit [post]
+func (c *VarietyController) Edit() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	var req request.EditVarietyReq
+	err := json.Unmarshal(c.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.ChartVarietyId <= 0 {
+		br.Msg = "请选择品种"
+		br.IsSendEmail = false
+		return
+	}
+	if req.VarietyName == "" {
+		br.Msg = "请输入品种名称"
+		br.IsSendEmail = false
+		return
+	}
+	varietyName := utils.TrimStr(req.VarietyName)
+
+	item, err := cross_variety.GetVarietyByName(varietyName)
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		br.Msg = "添加失败"
+		br.ErrMsg = "添加失败,Err:" + err.Error()
+		return
+	}
+	if item != nil && item.ChartVarietyId != req.ChartVarietyId {
+		br.Msg = "添加失败,品种名称不能重复"
+		br.IsSendEmail = false
+		return
+	}
+
+	// 获取品种详情
+	varietyInfo, err := cross_variety.GetVarietyById(req.ChartVarietyId)
+	if err != nil {
+		br.Msg = "查询品种失败"
+		br.ErrMsg = "查询品种失败;ERR:" + err.Error()
+		return
+	}
+
+	// 编辑
+	varietyInfo.ChartVarietyName = varietyName
+	varietyInfo.ModifyTime = time.Now()
+	err = varietyInfo.Update([]string{"ChartVarietyName", "ModifyTime"})
+	if err != nil {
+		br.Msg = "修改品种失败"
+		br.ErrMsg = "修改品种失败,Err:" + err.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Msg = "修改成功"
+	br.IsAddLog = true
+	br.Success = true
+}
+
+// DeleteCheck
+// @Title 删除品种检测接口
+// @Description 删除品种检测接口
+// @Param	request	body request.DelVarietyReq true "type json string"
+// @Success 200 Ret=200 检测成功
+// @router /variety/delete/check [post]
+func (c *VarietyController) DeleteCheck() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	var req request.DelVarietyReq
+	err := json.Unmarshal(c.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	if req.ChartVarietyId <= 0 {
+		br.Msg = "请选择品种"
+		br.IsSendEmail = false
+		return
+	}
+	var deleteStatus int
+	var tipsMsg string
+
+	// 获取该品种关联的图表数
+	count, err := cross_variety.GetCountChartByVarietyId(req.ChartVarietyId)
+	if err != nil {
+		br.Msg = "检测异常"
+		br.ErrMsg = "检测异常,err:" + err.Error()
+		br.IsSendEmail = false
+		return
+	}
+	if count > 0 {
+		deleteStatus = 1
+		tipsMsg = "已关联图表的品种,不允许删除!"
+	}
+
+	if deleteStatus == 0 {
+		tipsMsg = "可删除,进行删除操作"
+	}
+	resp := response.VarietyDeleteCheckResp{
+		DeleteStatus: deleteStatus,
+		TipsMsg:      tipsMsg,
+	}
+	br.Ret = 200
+	br.Msg = "检测成功"
+	br.Success = true
+	br.Data = resp
+}
+
+// Delete
+// @Title 删除品种
+// @Description 删除品种接口
+// @Param	request	body request.DeleteChartClassifyReq true "type json string"
+// @Success 200 Ret=200 删除成功
+// @router /variety/delete [post]
+func (c *VarietyController) Delete() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	var req request.DelVarietyReq
+	err := json.Unmarshal(c.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	if req.ChartVarietyId <= 0 {
+		br.Msg = "请选择品种"
+		br.IsSendEmail = false
+		return
+	}
+
+	// 获取该品种关联的图表数
+	count, err := cross_variety.GetCountChartByVarietyId(req.ChartVarietyId)
+	if err != nil {
+		br.Msg = "检测异常"
+		br.ErrMsg = "检测异常,err:" + err.Error()
+		br.IsSendEmail = false
+		return
+	}
+	if count > 0 {
+		br.Msg = "已关联图表的品种,不允许删除!"
+		br.ErrMsg = "已关联图表的品种,不允许删除!"
+		br.IsSendEmail = false
+		return
+	}
+
+	varietyInfo, err := cross_variety.GetVarietyById(req.ChartVarietyId)
+	if err != nil {
+		if err.Error() == utils.ErrNoRow() {
+			br.Msg = "该品种不存在或已删除"
+			br.IsSendEmail = false
+		} else {
+			br.Msg = "删除失败"
+			br.ErrMsg = "查找品种失败,ERR:" + err.Error()
+		}
+		return
+	}
+	err = varietyInfo.Delete()
+	if err != nil {
+		br.Msg = "删除失败"
+		br.ErrMsg = "删除品种失败,ERR:" + err.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Msg = "删除成功"
+	br.Success = true
+	br.IsAddLog = true
+}
+
+// List
+// @Title 获取标签中的指标与品种的映射关系
+// @Description 获取标签中的指标与品种的映射关系
+// @Success 200 Ret=200 保存成功
+// @router /variety/list [get]
+func (c *VarietyController) List() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	// 获取数据
+	list, err := cross_variety.GetVarietyList()
+	if err != nil {
+		br.Msg = "保存失败"
+		br.ErrMsg = "保存失败,ERR:" + err.Error()
+		return
+	}
+	dataCount := len(list)
+	page := paging.GetPaging(1, dataCount, dataCount)
+
+	resp := response.VarietyListResp{
+		List:   list,
+		Paging: page,
+	}
+
+	br.Ret = 200
+	br.Msg = "获取成功"
+	br.Success = true
+	br.Data = resp
+}

+ 628 - 135
controllers/data_manage/edb_info.go

@@ -9,6 +9,7 @@ import (
 	"eta/eta_mobile/models/data_manage/response"
 	"eta/eta_mobile/services/alarm_msg"
 	"eta/eta_mobile/services/data"
+	"eta/eta_mobile/services/data_stat"
 	"eta/eta_mobile/services/elastic"
 	"eta/eta_mobile/utils"
 	"fmt"
@@ -42,6 +43,8 @@ func (this *EdbInfoController) EdbInfoSearch() {
 	edbCode = strings.Trim(edbCode, "\t")
 	edbCode = strings.Trim(edbCode, " ")
 	edbCode = strings.Replace(edbCode, "\t", "", -1)
+	stockCode := this.GetString("StockCode")
+	subSource, _ := this.GetInt("SubSource")
 
 	if source <= 0 {
 		br.Msg = "无效的数据来源"
@@ -152,76 +155,59 @@ func (this *EdbInfoController) EdbInfoSearch() {
 
 		searchItem := new(data_manage.EdbInfoSearch)
 		if source == utils.DATA_SOURCE_THS {
-			dataItems, err := data_manage.GetEdbDataAllByEdbCode(edbCode, utils.DATA_SOURCE_THS, utils.EDB_DATA_LIMIT)
-			if err != nil && err.Error() != utils.ErrNoRow() {
-				br.Msg = "获取失败"
-				br.ErrMsg = "获取Ths已存在信息失败,Err:" + err.Error()
-				return
-			}
-
-			fmt.Println("ths len:", len(dataItems))
-			if len(dataItems) > 0 {
-				fmt.Println("ths data exist")
-				searchItem.EdbCode = edbCode
-				minDate, maxDate, err := data_manage.GetEdbDataThsMaxOrMinDate(edbCode)
-				if err != nil {
+			fmt.Println("subSource:", subSource)
+			if subSource == utils.DATA_SUB_SOURCE_EDB {
+				dataItems, err := data_manage.GetEdbDataAllByEdbCode(edbCode, utils.DATA_SOURCE_THS, subSource, utils.EDB_DATA_LIMIT)
+				if err != nil && err.Error() != utils.ErrNoRow() {
 					br.Msg = "获取失败"
-					br.ErrMsg = "获取Ths日期信息失败,Err:" + err.Error()
+					br.ErrMsg = "获取Ths已存在信息失败,Err:" + err.Error()
 					return
 				}
-				searchItem.DataList = dataItems
-				searchItem.StartDate = minDate
-				searchItem.EndDate = maxDate
-			} else {
-				//endDate := dateNow.AddDate(utils.DATA_END_DATE_LIMIT, 0, 0).Format(utils.FormatDate)
-				//searchItem, err = data.GetEdbDataByThs(edbCode, startDate, endDate)
-				//if err != nil {
-				//	br.Msg = "获取失败"
-				//	br.ErrMsg = "获取失败,Err:" + err.Error()
-				//	return
-				//}
-				respItem, err := data.AddEdbData(source, edbCode)
-				if err != nil {
-					br.Msg = "获取失败"
-					br.ErrMsg = "获取失败,Err:" + err.Error()
-					return
+
+				fmt.Println("ths len:", len(dataItems))
+				if len(dataItems) > 0 {
+					fmt.Println("ths data exist")
+					searchItem.EdbCode = edbCode
+					minDate, maxDate, err := data_manage.GetEdbDataThsMaxOrMinDate(edbCode)
+					if err != nil {
+						br.Msg = "获取失败"
+						br.ErrMsg = "获取Ths日期信息失败,Err:" + err.Error()
+						return
+					}
+					searchItem.DataList = dataItems
+					searchItem.StartDate = minDate
+					searchItem.EndDate = maxDate
+				} else {
+					//endDate := dateNow.AddDate(utils.DATA_END_DATE_LIMIT, 0, 0).Format(utils.FormatDate)
+					//searchItem, err = data.GetEdbDataByThs(edbCode, startDate, endDate)
+					//if err != nil {
+					//	br.Msg = "获取失败"
+					//	br.ErrMsg = "获取失败,Err:" + err.Error()
+					//	return
+					//}
+					respItem, err := data.AddEdbData(source, edbCode)
+					if err != nil {
+						br.Msg = "获取失败"
+						br.ErrMsg = "获取失败,Err:" + err.Error()
+						return
+					}
+					if respItem.Ret != 200 {
+						br.Msg = "未搜索到该指标"
+						br.ErrMsg = respItem.ErrMsg + ";EdbCode:" + edbCode
+						return
+					}
+					isAdd = true
 				}
-				if respItem.Ret != 200 {
-					br.Msg = "未搜索到该指标"
-					br.ErrMsg = respItem.ErrMsg + ";EdbCode:" + edbCode
+			} else if subSource == utils.DATA_SUB_SOURCE_DATE {
+				if stockCode == "" {
+					br.Msg = "请输入证券代码"
 					return
 				}
-				isAdd = true
-			}
-		} else if source == utils.DATA_SOURCE_WIND {
-			fmt.Println("wind data exist")
-			dataItems, err := data_manage.GetEdbDataAllByEdbCode(edbCode, utils.DATA_SOURCE_WIND, utils.EDB_DATA_LIMIT)
-			if err != nil && err.Error() != utils.ErrNoRow() {
-				br.Msg = "获取失败"
-				br.ErrMsg = "获取Wind已存在信息失败,Err:" + err.Error()
-				return
-			}
-			fmt.Println("wind dataItems:", len(dataItems))
-			if len(dataItems) > 0 {
-				searchItem.EdbCode = edbCode
-				minDate, maxDate, err := data_manage.GetEdbDataWindMaxOrMinDate(edbCode)
-				if err != nil {
-					br.Msg = "获取失败"
-					br.ErrMsg = "获取wind日期信息失败,Err:" + err.Error()
+				if edbCode == "" {
+					br.Msg = "请输入指标代码"
 					return
 				}
-				searchItem.DataList = dataItems
-				searchItem.StartDate = minDate
-				searchItem.EndDate = maxDate
-			} else {
-				//endDate := dateNow.Format(utils.FormatDate)
-				//searchItem, err = data.GetEdbDataByWind(edbCode, startDate, endDate)
-				//if err != nil {
-				//	br.Msg = "获取失败"
-				//	br.ErrMsg = "wind 获取失败,Err:" + err.Error()
-				//	return
-				//}
-				respItem, err := data.AddEdbData(source, edbCode)
+				respItem, err := data.AddEdbDataThsDs(source, stockCode, edbCode)
 				if err != nil {
 					br.Msg = "获取失败"
 					br.ErrMsg = "获取失败,Err:" + err.Error()
@@ -230,6 +216,8 @@ func (this *EdbInfoController) EdbInfoSearch() {
 				if respItem.Ret != 200 {
 					if respItem.Ret == 421 {
 						br.Msg = "该渠道已超过添加上限"
+					} else if respItem.Ret == 4052 {
+						br.Msg = "该指标已下架"
 					} else {
 						br.Msg = "未搜索到该指标"
 					}
@@ -237,10 +225,62 @@ func (this *EdbInfoController) EdbInfoSearch() {
 					return
 				}
 				isAdd = true
+			} else {
+				br.Msg = "无效的渠道来源"
+				return
+			}
+		} else if source == utils.DATA_SOURCE_WIND {
+			fmt.Println("subSource:", subSource)
+			if subSource == utils.DATA_SUB_SOURCE_EDB {
+				dataItems, err := data_manage.GetEdbDataAllByEdbCode(edbCode, utils.DATA_SOURCE_WIND, subSource, utils.EDB_DATA_LIMIT)
+				if err != nil && err.Error() != utils.ErrNoRow() {
+					br.Msg = "获取失败"
+					br.ErrMsg = "获取Wind已存在信息失败,Err:" + err.Error()
+					return
+				}
+				fmt.Println("wind dataItems:", len(dataItems))
+				if len(dataItems) > 0 {
+					searchItem.EdbCode = edbCode
+					minDate, maxDate, err := data_manage.GetEdbDataWindMaxOrMinDate(edbCode)
+					if err != nil {
+						br.Msg = "获取失败"
+						br.ErrMsg = "获取wind日期信息失败,Err:" + err.Error()
+						return
+					}
+					searchItem.DataList = dataItems
+					searchItem.StartDate = minDate
+					searchItem.EndDate = maxDate
+				} else {
+					//endDate := dateNow.Format(utils.FormatDate)
+					//searchItem, err = data.GetEdbDataByWind(edbCode, startDate, endDate)
+					//if err != nil {
+					//	br.Msg = "获取失败"
+					//	br.ErrMsg = "wind 获取失败,Err:" + err.Error()
+					//	return
+					//}
+					respItem, err := data.AddEdbData(source, edbCode)
+					if err != nil {
+						br.Msg = "获取失败"
+						br.ErrMsg = "获取失败,Err:" + err.Error()
+						return
+					}
+					if respItem.Ret != 200 {
+						if respItem.Ret == 421 {
+							br.Msg = "该渠道已超过添加上限"
+						} else if respItem.Ret == 4052 {
+							br.Msg = "该指标已下架"
+						} else {
+							br.Msg = "未搜索到该指标"
+						}
+						br.ErrMsg = respItem.ErrMsg + ";EdbCode:" + edbCode
+						return
+					}
+					isAdd = true
+				}
 			}
 		} else if source == utils.DATA_SOURCE_PB || source == utils.DATA_SOURCE_PB_FINANCE {
 			fmt.Println("pb data exist")
-			dataItems, err := data_manage.GetEdbDataAllByEdbCode(edbCode, source, utils.EDB_DATA_LIMIT)
+			dataItems, err := data_manage.GetEdbDataAllByEdbCode(edbCode, source, subSource, utils.EDB_DATA_LIMIT)
 			if err != nil && err.Error() != utils.ErrNoRow() {
 				br.Msg = "获取失败"
 				br.ErrMsg = "获取Pb已存在信息失败,Err:" + err.Error()
@@ -281,7 +321,7 @@ func (this *EdbInfoController) EdbInfoSearch() {
 				isAdd = true
 			}
 		} else if source == utils.DATA_SOURCE_MANUAL { //手工数据指标
-			dataItems, err := data_manage.GetEdbDataAllByEdbCode(edbCode, utils.DATA_SOURCE_MANUAL, utils.EDB_DATA_LIMIT)
+			dataItems, err := data_manage.GetEdbDataAllByEdbCode(edbCode, utils.DATA_SOURCE_MANUAL, subSource, utils.EDB_DATA_LIMIT)
 			if err != nil && err.Error() != utils.ErrNoRow() {
 				br.Msg = "获取失败"
 				br.ErrMsg = "获取Ths已存在信息失败,Err:" + err.Error()
@@ -335,7 +375,7 @@ func (this *EdbInfoController) EdbInfoSearch() {
 			}
 
 		} else if source == utils.DATA_SOURCE_LZ {
-			dataItems, err := data_manage.GetEdbDataAllByEdbCode(edbCode, utils.DATA_SOURCE_LZ, utils.EDB_DATA_LIMIT)
+			dataItems, err := data_manage.GetEdbDataAllByEdbCode(edbCode, utils.DATA_SOURCE_LZ, subSource, utils.EDB_DATA_LIMIT)
 			if err != nil && err.Error() != utils.ErrNoRow() {
 				br.Msg = "获取失败"
 				br.ErrMsg = "获取隆众已存在信息失败,Err:" + err.Error()
@@ -404,7 +444,7 @@ func (this *EdbInfoController) EdbInfoSearch() {
 				searchItem.EdbName = lzInfo.SampleName + lzInfo.BreedName + lzInfo.QuotaName
 			}
 		} else if source == utils.DATA_SOURCE_YS { //有色网
-			dataItems, err := data_manage.GetEdbDataAllByEdbCode(edbCode, utils.DATA_SOURCE_YS, utils.EDB_DATA_LIMIT)
+			dataItems, err := data_manage.GetEdbDataAllByEdbCode(edbCode, utils.DATA_SOURCE_YS, subSource, utils.EDB_DATA_LIMIT)
 			if err != nil && err.Error() != utils.ErrNoRow() {
 				br.Msg = "获取失败"
 				br.ErrMsg = "获取Ys已存在信息失败,Err:" + err.Error()
@@ -464,7 +504,7 @@ func (this *EdbInfoController) EdbInfoSearch() {
 			}
 
 		} else if source == utils.DATA_SOURCE_GL { //钢联
-			dataItems, err := data_manage.GetEdbDataAllByEdbCode(edbCode, source, utils.EDB_DATA_LIMIT)
+			dataItems, err := data_manage.GetEdbDataAllByEdbCode(edbCode, source, subSource, utils.EDB_DATA_LIMIT)
 			if err != nil && err.Error() != utils.ErrNoRow() {
 				br.Msg = "获取失败"
 				br.ErrMsg = "获取钢联已存在信息失败,Err:" + err.Error()
@@ -528,7 +568,7 @@ func (this *EdbInfoController) EdbInfoSearch() {
 				br.ErrMsg = "指标code异常"
 				return
 			}
-			dataItems, err := data_manage.GetEdbDataAllByEdbCode(edbCode, source, utils.EDB_DATA_LIMIT)
+			dataItems, err := data_manage.GetEdbDataAllByEdbCode(edbCode, source, subSource, utils.EDB_DATA_LIMIT)
 			if err != nil && err.Error() != utils.ErrNoRow() {
 				br.Msg = "获取失败"
 				br.ErrMsg = "获取郑商所已存在信息失败,Err:" + err.Error()
@@ -606,7 +646,7 @@ func (this *EdbInfoController) EdbInfoSearch() {
 				br.ErrMsg = "指标code异常"
 				return
 			}
-			dataItems, err := data_manage.GetEdbDataAllByEdbCode(edbCode, source, utils.EDB_DATA_LIMIT)
+			dataItems, err := data_manage.GetEdbDataAllByEdbCode(edbCode, source, subSource, utils.EDB_DATA_LIMIT)
 			if err != nil && err.Error() != utils.ErrNoRow() {
 				br.Msg = "获取失败"
 				br.ErrMsg = "获取大商所已存在信息失败,Err:" + err.Error()
@@ -685,7 +725,7 @@ func (this *EdbInfoController) EdbInfoSearch() {
 				br.ErrMsg = "指标code异常"
 				return
 			}
-			dataItems, err := data_manage.GetEdbDataAllByEdbCode(edbCode, source, utils.EDB_DATA_LIMIT)
+			dataItems, err := data_manage.GetEdbDataAllByEdbCode(edbCode, source, subSource, utils.EDB_DATA_LIMIT)
 			if err != nil && err.Error() != utils.ErrNoRow() {
 				br.Msg = "获取失败"
 				br.ErrMsg = "获取上期所已存在信息失败,Err:" + err.Error()
@@ -764,7 +804,7 @@ func (this *EdbInfoController) EdbInfoSearch() {
 				br.ErrMsg = "指标code异常"
 				return
 			}
-			dataItems, err := data_manage.GetEdbDataAllByEdbCode(edbCode, source, utils.EDB_DATA_LIMIT)
+			dataItems, err := data_manage.GetEdbDataAllByEdbCode(edbCode, source, subSource, utils.EDB_DATA_LIMIT)
 			if err != nil && err.Error() != utils.ErrNoRow() {
 				br.Msg = "获取失败"
 				br.ErrMsg = "获取中金所已存在信息失败,Err:" + err.Error()
@@ -843,7 +883,7 @@ func (this *EdbInfoController) EdbInfoSearch() {
 				br.ErrMsg = "指标code异常"
 				return
 			}
-			dataItems, err := data_manage.GetEdbDataAllByEdbCode(edbCode, source, utils.EDB_DATA_LIMIT)
+			dataItems, err := data_manage.GetEdbDataAllByEdbCode(edbCode, source, subSource, utils.EDB_DATA_LIMIT)
 			if err != nil && err.Error() != utils.ErrNoRow() {
 				br.Msg = "获取失败"
 				br.ErrMsg = "获取上期能源已存在信息失败,Err:" + err.Error()
@@ -937,7 +977,7 @@ func (this *EdbInfoController) EdbInfoSearch() {
 				br.ErrMsg = "指标code异常"
 				return
 			}
-			dataItems, err := data_manage.GetEdbDataAllByEdbCode(edbCode, source, utils.EDB_DATA_LIMIT)
+			dataItems, err := data_manage.GetEdbDataAllByEdbCode(edbCode, source, subSource, utils.EDB_DATA_LIMIT)
 			if err != nil && err.Error() != utils.ErrNoRow() {
 				br.Msg = "获取失败"
 				br.ErrMsg = "获取欧洲天然气已存在信息失败,Err:" + err.Error()
@@ -1045,7 +1085,7 @@ func (this *EdbInfoController) EdbInfoSearch() {
 				br.ErrMsg = "暂不支持编码中含有=的指标"
 				return
 			}
-			dataItems, err := data_manage.GetEdbDataAllByEdbCode(edbCode, utils.DATA_SOURCE_LT, utils.EDB_DATA_LIMIT)
+			dataItems, err := data_manage.GetEdbDataAllByEdbCode(edbCode, utils.DATA_SOURCE_LT, subSource, utils.EDB_DATA_LIMIT)
 			if err != nil && err.Error() != utils.ErrNoRow() {
 				br.Msg = "获取失败"
 				br.ErrMsg = "获取 lt 已存在信息失败,Err:" + err.Error()
@@ -1054,7 +1094,7 @@ func (this *EdbInfoController) EdbInfoSearch() {
 			fmt.Println("lt dataItems:", len(dataItems))
 			if len(dataItems) > 0 {
 				searchItem.EdbCode = edbCode
-				edbInfoMaxAndMinInfo, err := data_manage.GetEdbInfoMaxAndMinInfo(source, edbCode)
+				edbInfoMaxAndMinInfo, err := data_manage.GetEdbInfoMaxAndMinInfo(source, subSource, edbCode)
 				if err != nil {
 					br.Msg = "获取失败"
 					br.ErrMsg = "获取lt日期信息失败,Err:" + err.Error()
@@ -1101,7 +1141,7 @@ func (this *EdbInfoController) EdbInfoSearch() {
 				br.ErrMsg = "指标code异常"
 				return
 			}
-			dataItems, err := data_manage.GetEdbDataAllByEdbCode(edbCode, source, utils.EDB_DATA_LIMIT)
+			dataItems, err := data_manage.GetEdbDataAllByEdbCode(edbCode, source, subSource, utils.EDB_DATA_LIMIT)
 			if err != nil && err.Error() != utils.ErrNoRow() {
 				br.Msg = "获取失败"
 				br.ErrMsg = "获取煤炭网已存在信息失败,Err:" + err.Error()
@@ -1162,7 +1202,7 @@ func (this *EdbInfoController) EdbInfoSearch() {
 				searchItem.EdbName = coalInfo.IndexName
 			}
 		} else if source == utils.DATA_SOURCE_GOOGLE_TRAVEL { //谷歌出行数据
-			dataItems, err := data_manage.GetEdbDataAllByEdbCode(edbCode, source, utils.EDB_DATA_LIMIT)
+			dataItems, err := data_manage.GetEdbDataAllByEdbCode(edbCode, source, subSource, utils.EDB_DATA_LIMIT)
 			if err != nil && err.Error() != utils.ErrNoRow() {
 				br.Msg = "获取失败"
 				br.ErrMsg = "获取煤炭网已存在信息失败,Err:" + err.Error()
@@ -1171,7 +1211,7 @@ func (this *EdbInfoController) EdbInfoSearch() {
 
 			if len(dataItems) > 0 {
 				searchItem.EdbCode = edbCode
-				item, err := data_manage.GetEdbInfoMaxAndMinInfo(source, edbCode)
+				item, err := data_manage.GetEdbInfoMaxAndMinInfo(source, subSource, edbCode)
 				if err != nil {
 					br.Msg = "获取失败"
 					br.ErrMsg = "获取煤炭网日期信息失败,Err:" + err.Error()
@@ -1197,7 +1237,7 @@ func (this *EdbInfoController) EdbInfoSearch() {
 				isAdd = true
 			}
 		} else if source == utils.DATA_SOURCE_MYSTEEL_CHEMICAL { //钢联化工
-			dataItems, err := data_manage.GetEdbDataAllByEdbCode(edbCode, source, utils.EDB_DATA_LIMIT)
+			dataItems, err := data_manage.GetEdbDataAllByEdbCode(edbCode, source, subSource, utils.EDB_DATA_LIMIT)
 			if err != nil && err.Error() != utils.ErrNoRow() {
 				br.Msg = "获取失败"
 				br.ErrMsg = "获取钢联已存在信息失败,Err:" + err.Error()
@@ -1249,7 +1289,7 @@ func (this *EdbInfoController) EdbInfoSearch() {
 				searchItem.EdbName = glInfo.IndexName
 			}
 		} else if source == utils.DATA_SOURCE_EIA_STEO { //eia steo报告
-			dataItems, err := data_manage.GetEdbDataAllByEdbCode(edbCode, source, utils.EDB_DATA_LIMIT)
+			dataItems, err := data_manage.GetEdbDataAllByEdbCode(edbCode, source, subSource, utils.EDB_DATA_LIMIT)
 			if err != nil && err.Error() != utils.ErrNoRow() {
 				br.Msg = "获取失败"
 				br.ErrMsg = "获取钢联已存在信息失败,Err:" + err.Error()
@@ -1258,7 +1298,7 @@ func (this *EdbInfoController) EdbInfoSearch() {
 
 			if len(dataItems) > 0 {
 				searchItem.EdbCode = edbCode
-				item, err := data_manage.GetEdbInfoMaxAndMinInfo(source, edbCode)
+				item, err := data_manage.GetEdbInfoMaxAndMinInfo(source, subSource, edbCode)
 				if err != nil {
 					br.Msg = "获取失败"
 					br.ErrMsg = "获取eia steo日期信息失败,Err:" + err.Error()
@@ -1294,7 +1334,7 @@ func (this *EdbInfoController) EdbInfoSearch() {
 				searchItem.EdbName = eiasteoInfo.IndexName
 			}
 		} else if source == utils.DATA_SOURCE_COM_TRADE { // un数据源
-			dataItems, err := data_manage.GetEdbDataAllByEdbCode(edbCode, source, utils.EDB_DATA_LIMIT)
+			dataItems, err := data_manage.GetEdbDataAllByEdbCode(edbCode, source, subSource, utils.EDB_DATA_LIMIT)
 			if err != nil && err.Error() != utils.ErrNoRow() {
 				br.Msg = "获取失败"
 				br.ErrMsg = "获取联合国商品贸易数据已存在信息失败,Err:" + err.Error()
@@ -1303,7 +1343,7 @@ func (this *EdbInfoController) EdbInfoSearch() {
 
 			if len(dataItems) > 0 {
 				searchItem.EdbCode = edbCode
-				item, err := data_manage.GetEdbInfoMaxAndMinInfo(source, edbCode)
+				item, err := data_manage.GetEdbInfoMaxAndMinInfo(source, subSource, edbCode)
 				if err != nil {
 					br.Msg = "获取失败"
 					br.ErrMsg = "获取联合国商品贸易数据日期信息失败,Err:" + err.Error()
@@ -1348,7 +1388,7 @@ func (this *EdbInfoController) EdbInfoSearch() {
 				searchItem.EdbName = eiasteoInfo.Name
 			}
 		} else if source == utils.DATA_SOURCE_SCI { //卓创数据(红桃三)
-			dataItems, err := data_manage.GetEdbDataAllByEdbCode(edbCode, source, utils.EDB_DATA_LIMIT)
+			dataItems, err := data_manage.GetEdbDataAllByEdbCode(edbCode, source, subSource, utils.EDB_DATA_LIMIT)
 			if err != nil && err.Error() != utils.ErrNoRow() {
 				br.Msg = "获取失败"
 				br.ErrMsg = "获取SCI已存在信息失败,Err:" + err.Error()
@@ -1408,7 +1448,7 @@ func (this *EdbInfoController) EdbInfoSearch() {
 			}
 
 		} else if source == utils.DATA_SOURCE_BAIINFO { //百川盈孚
-			dataItems, err := data_manage.GetEdbDataAllByEdbCode(edbCode, source, utils.EDB_DATA_LIMIT)
+			dataItems, err := data_manage.GetEdbDataAllByEdbCode(edbCode, source, subSource, utils.EDB_DATA_LIMIT)
 			if err != nil && err.Error() != utils.ErrNoRow() {
 				br.Msg = "获取失败"
 				br.ErrMsg = "获取BAIINFO已存在信息失败,Err:" + err.Error()
@@ -1468,7 +1508,7 @@ func (this *EdbInfoController) EdbInfoSearch() {
 			}
 
 		} else if source == utils.DATA_SOURCE_NATIONAL_STATISTICS { // 国家统计局
-			dataItems, err := data_manage.GetEdbDataAllByEdbCode(edbCode, source, utils.EDB_DATA_LIMIT)
+			dataItems, err := data_manage.GetEdbDataAllByEdbCode(edbCode, source, subSource, utils.EDB_DATA_LIMIT)
 			if err != nil && err.Error() != utils.ErrNoRow() {
 				br.Msg = "获取失败"
 				br.ErrMsg = "获取国家统计局已存在信息失败,Err:" + err.Error()
@@ -1477,7 +1517,7 @@ func (this *EdbInfoController) EdbInfoSearch() {
 
 			if len(dataItems) > 0 {
 				searchItem.EdbCode = edbCode
-				item, err := data_manage.GetEdbInfoMaxAndMinInfo(source, edbCode)
+				item, err := data_manage.GetEdbInfoMaxAndMinInfo(source, subSource, edbCode)
 				if err != nil {
 					br.Msg = "获取失败"
 					br.ErrMsg = "获取国家统计局日期信息失败,Err:" + err.Error()
@@ -1513,7 +1553,7 @@ func (this *EdbInfoController) EdbInfoSearch() {
 				searchItem.EdbName = fmt.Sprintf("%s%s", nationalInfo.Reg, nationalInfo.IndexName)
 			}
 		} else if source == utils.DATA_SOURCE_FUBAO { //数宝
-			dataItems, err := data_manage.GetEdbDataAllByEdbCode(edbCode, utils.DATA_SOURCE_FUBAO, utils.EDB_DATA_LIMIT)
+			dataItems, err := data_manage.GetEdbDataAllByEdbCode(edbCode, utils.DATA_SOURCE_FUBAO, subSource, utils.EDB_DATA_LIMIT)
 			if err != nil && err.Error() != utils.ErrNoRow() {
 				br.Msg = "获取失败"
 				br.ErrMsg = "获取Fubao已存在信息失败,Err:" + err.Error()
@@ -1556,7 +1596,7 @@ func (this *EdbInfoController) EdbInfoSearch() {
 			}
 
 			// 获取指标数据
-			dataList, e := data_manage.GetEdbDataAllByEdbCode(edbCode, source, utils.EDB_DATA_LIMIT)
+			dataList, e := data_manage.GetEdbDataAllByEdbCode(edbCode, source, subSource, utils.EDB_DATA_LIMIT)
 			if e != nil {
 				br.Msg = "获取失败"
 				br.ErrMsg = "获取指标数据失败, Err: " + e.Error()
@@ -1566,7 +1606,7 @@ func (this *EdbInfoController) EdbInfoSearch() {
 				searchItem.EdbCode = edbCode
 				searchItem.DataList = dataList
 				// 获取最大最小值
-				edbInfoMaxAndMinInfo, e := data_manage.GetEdbInfoMaxAndMinInfo(source, edbCode)
+				edbInfoMaxAndMinInfo, e := data_manage.GetEdbInfoMaxAndMinInfo(source, subSource, edbCode)
 				if e != nil && e.Error() != utils.ErrNoRow() {
 					br.Msg = "获取失败"
 					br.ErrMsg = "获取数据失败, GetEdbInfoMaxAndMinInfo Err:" + e.Error()
@@ -1597,7 +1637,13 @@ func (this *EdbInfoController) EdbInfoSearch() {
 				}
 				isAdd = true
 			}
-
+			// 查询基本信息
+			baseIndexInfo, tErr := data_manage.GetBaseIndexInfoByEdbCode(edbCode, source)
+			if tErr == nil {
+				searchItem.EdbName = baseIndexInfo.IndexName
+				searchItem.Frequency = baseIndexInfo.Frequency
+				searchItem.Unit = baseIndexInfo.Unit
+			}
 			// 指标来源于桥接服务: 桥接服务获取指标取频度信息等
 			if sourceItem.BridgeFlag != "" {
 				bridgeOb := data.InitBridgeOB(sourceItem.BridgeFlag)
@@ -1620,32 +1666,143 @@ func (this *EdbInfoController) EdbInfoSearch() {
 			}
 		}
 		if isAdd {
-			dataList, err := data_manage.GetEdbDataAllByEdbCode(edbCode, source, utils.EDB_DATA_LIMIT)
-			if err != nil && err.Error() != utils.ErrNoRow() {
-				br.Msg = "获取失败"
-				br.ErrMsg = "获取数据失败,GetEdbDataAllByEdbCode Err:" + err.Error()
-				return
-			}
-			searchItem.DataList = dataList
+			if subSource == utils.DATA_SUB_SOURCE_DATE {
+				if source == utils.DATA_SOURCE_WIND {
+					//wsdData := windWsdRespItem.Data
+					//var buf bytes.Buffer
+					//// 创建一个encoder并指定目标为buf
+					//enc := gob.NewEncoder(&buf)
+					//
+					//// 将data编码到buf中
+					//err = enc.Encode(wsdData)
+					//if err != nil {
+					//	br.Msg = "获取失败"
+					//	br.ErrMsg = "获取数据失败,wind wsd encoding GOB Err:" + err.Error()
+					//	return
+					//}
+					//
+					//wsdDataMap := make(map[string]map[string]interface{})
+					//err = json.Unmarshal(buf.Bytes(), &wsdDataMap)
+					//if err != nil {
+					//	br.Msg = "获取失败"
+					//	br.ErrMsg = "获取数据失败,wind wsd json.Unmarshal Err:" + err.Error()
+					//	return
+					//}
+					//
+					//stockList := make([]*data_manage.StockInfo, 0)
+					//
+					//dataList := make([]*data_manage.EdbInfoSearchData, 0)
+					//for wk, wv := range wsdDataMap {
+					//	for vk, vv := range wv {
+					//		wkInt, err := strconv.ParseInt(wk, 10, 64)
+					//		if err != nil {
+					//			br.Msg = "获取失败"
+					//			br.ErrMsg = "获取数据失败,转换日期类型失败 Err:" + err.Error()
+					//			return
+					//		}
+					//
+					//		vk = strings.ToLower(vk)
+					//		wkInt = wkInt / 1000
+					//		t := time.Unix(wkInt, 0)
+					//		dateTime := t.Format(utils.FormatDate)
+					//		//saveVal := utils.SubFloatToString(val, 20)
+					//		if vv == nil {
+					//			continue
+					//		}
+					//		var saveVal string
+					//		switch vt := vv.(type) {
+					//		case int:
+					//			saveVal = strconv.Itoa(vt)
+					//		case float64:
+					//			saveVal = utils.SubFloatToFloatStr(vt, 20)
+					//		case string:
+					//			saveVal = vt
+					//		}
+					//
+					//		dataItem := new(data_manage.EdbInfoSearchData)
+					//		dataItem.Value = saveVal
+					//		dataItem.DataTime = dateTime
+					//		dataList = append(dataList, dataItem)
+					//		if len(dataList) >= 10 {
+					//			break
+					//		}
+					//	}
+					//}
+					//searchItem.StockList = stockList
+
+					stockList := make([]*data_manage.StockInfo, 0)
+					edbCodeArr := strings.Split(edbCode, ",")
+					for _, v := range edbCodeArr {
+						indexCode := utils.WindDbWsd + stockCode + v
+
+						dataList, err := data_manage.GetEdbDataAllByEdbCodeAndSubSource(indexCode, source, utils.DATA_SUB_SOURCE_DATE, utils.EDB_DATA_LIMIT)
+						if err != nil && err.Error() != utils.ErrNoRow() {
+							br.Msg = "获取失败"
+							br.ErrMsg = "获取数据失败,GetEdbDataAllByEdbCode Err:" + err.Error()
+							return
+						}
+
+						stockInfo := new(data_manage.StockInfo)
+						stockInfo.StockCode = stockCode
+						stockInfo.EdbCode = v
+						stockInfo.DataList = dataList
+						stockList = append(stockList, stockInfo)
+					}
+					searchItem.StockList = stockList
+				} else if source == utils.DATA_SOURCE_THS {
+					stockList := make([]*data_manage.StockInfo, 0)
+					edbCodeArr := strings.Split(edbCode, ",")
+					for _, v := range edbCodeArr {
+						indexCode := utils.ThsDs + stockCode + v
+
+						dataList, err := data_manage.GetEdbDataAllByEdbCodeAndSubSource(indexCode, source, utils.DATA_SUB_SOURCE_DATE, utils.EDB_DATA_LIMIT)
+						if err != nil && err.Error() != utils.ErrNoRow() {
+							br.Msg = "获取失败"
+							br.ErrMsg = "获取数据失败,GetEdbDataAllByEdbCode Err:" + err.Error()
+							return
+						}
+
+						stockInfo := new(data_manage.StockInfo)
+						stockInfo.StockCode = stockCode
+						stockInfo.EdbCode = v
+						stockInfo.DataList = dataList
+						stockList = append(stockList, stockInfo)
+					}
+					searchItem.StockList = stockList
+				} else {
+					br.Msg = "来源错误"
+					br.ErrMsg = "来源错误"
+					return
+				}
+			} else {
+				dataList, err := data_manage.GetEdbDataAllByEdbCode(edbCode, source, subSource, utils.EDB_DATA_LIMIT)
+				if err != nil && err.Error() != utils.ErrNoRow() {
+					br.Msg = "获取失败"
+					br.ErrMsg = "获取数据失败,GetEdbDataAllByEdbCode Err:" + err.Error()
+					return
+				}
+				searchItem.DataList = dataList
 
-			edbInfoMaxAndMinInfo, err := data_manage.GetEdbInfoMaxAndMinInfo(source, edbCode)
-			if err != nil && err.Error() != utils.ErrNoRow() {
-				br.Msg = "获取失败"
-				br.ErrMsg = "获取数据失败,GetEdbInfoMaxAndMinInfo Err:" + err.Error()
-				return
-			}
-			searchItem.EdbCode = edbCode
-			searchItem.DataList = dataList
-			if edbInfoMaxAndMinInfo != nil {
-				searchItem.StartDate = edbInfoMaxAndMinInfo.MinDate
-				searchItem.EndDate = edbInfoMaxAndMinInfo.MaxDate
-			}
+				edbInfoMaxAndMinInfo, err := data_manage.GetEdbInfoMaxAndMinInfo(source, subSource, edbCode)
+				if err != nil && err.Error() != utils.ErrNoRow() {
+					br.Msg = "获取失败"
+					br.ErrMsg = "获取数据失败,GetEdbInfoMaxAndMinInfo Err:" + err.Error()
+					return
+				}
+				searchItem.EdbCode = edbCode
+				searchItem.DataList = dataList
+				if edbInfoMaxAndMinInfo != nil {
+					searchItem.StartDate = edbInfoMaxAndMinInfo.MinDate
+					searchItem.EndDate = edbInfoMaxAndMinInfo.MaxDate
+				}
 
-			//edb指标信息
-			edbInfoItem, err := data_manage.GetEdbInfoByEdbCode(source, edbCode)
-			if edbInfoItem != nil {
-				searchItem.EdbName = edbInfoItem.EdbName
+				//edb指标信息
+				edbInfoItem, err := data_manage.GetEdbInfoByEdbCode(source, edbCode)
+				if edbInfoItem != nil {
+					searchItem.EdbName = edbInfoItem.EdbName
+				}
 			}
+
 		}
 		resp.Status = 2
 		resp.SearchItem = searchItem
@@ -1773,20 +1930,58 @@ func (this *EdbInfoController) EdbInfoList() {
 	dataCondition += ` AND edb_info_id=? `
 	dataPars = append(dataPars, edbInfoItem.EdbInfoId)
 
-	dataCount, err := data_manage.GetEdbDataCountByCondition(dataCondition, dataPars, edbInfoItem.Source)
-	if err != nil && err.Error() != utils.ErrNoRow() {
-		br.Msg = "获取指标信息失败"
-		br.ErrMsg = "获取指标数据总数失败,Err:" + err.Error()
-		return
-	}
-	page = paging.GetPaging(currentIndex, pageSize, dataCount)
-	dataList, err := data_manage.GetEdbDataListByCondition(dataCondition, dataPars, edbInfoItem.Source, pageSize, startSize)
-	if err != nil {
-		br.Msg = "获取指标信息失败"
-		br.ErrMsg = "获取指标数据失败,Err:" + err.Error()
-		return
+	if edbInfoItem.SubSource == utils.DATA_SUB_SOURCE_DATE {
+		if edbInfoItem.Source == utils.DATA_SOURCE_WIND {
+			dataCount, err := data_manage.GetEdbWsdDataCountByCondition(dataCondition, dataPars, edbInfoItem.Source)
+			if err != nil && err.Error() != utils.ErrNoRow() {
+				br.Msg = "获取指标信息失败"
+				br.ErrMsg = "获取指标数据总数失败,Err:" + err.Error()
+				return
+			}
+			page = paging.GetPaging(currentIndex, pageSize, dataCount)
+			dataList, err := data_manage.GetEdbWsdDataListByCondition(dataCondition, dataPars, edbInfoItem.Source, pageSize, startSize)
+			if err != nil {
+				br.Msg = "获取指标信息失败"
+				br.ErrMsg = "获取指标数据失败,Err:" + err.Error()
+				return
+			}
+			edbInfoItem.DataList = dataList
+		} else if edbInfoItem.Source == utils.DATA_SOURCE_THS {
+			dataCount, err := data_manage.GetTHsDsDataCountByCondition(dataCondition, dataPars, edbInfoItem.Source)
+			if err != nil && err.Error() != utils.ErrNoRow() {
+				br.Msg = "获取指标信息失败"
+				br.ErrMsg = "获取指标数据总数失败,Err:" + err.Error()
+				return
+			}
+			page = paging.GetPaging(currentIndex, pageSize, dataCount)
+			dataList, err := data_manage.GetThsDsDataListByCondition(dataCondition, dataPars, edbInfoItem.Source, pageSize, startSize)
+			if err != nil {
+				br.Msg = "获取指标信息失败"
+				br.ErrMsg = "获取指标数据失败,Err:" + err.Error()
+				return
+			}
+			edbInfoItem.DataList = dataList
+		} else {
+			br.Msg = "指标数据源id错误"
+			br.ErrMsg = "指标数据源id错误"
+			return
+		}
+	} else {
+		dataCount, err := data_manage.GetEdbDataCountByCondition(dataCondition, dataPars, edbInfoItem.Source, edbInfoItem.SubSource)
+		if err != nil && err.Error() != utils.ErrNoRow() {
+			br.Msg = "获取指标信息失败"
+			br.ErrMsg = "获取指标数据总数失败,Err:" + err.Error()
+			return
+		}
+		page = paging.GetPaging(currentIndex, pageSize, dataCount)
+		dataList, err := data_manage.GetEdbDataListByCondition(dataCondition, dataPars, edbInfoItem.Source, edbInfoItem.SubSource, pageSize, startSize)
+		if err != nil {
+			br.Msg = "获取指标信息失败"
+			br.ErrMsg = "获取指标数据失败,Err:" + err.Error()
+			return
+		}
+		edbInfoItem.DataList = dataList
 	}
-	edbInfoItem.DataList = dataList
 
 	// 获取指标插入配置
 	{
@@ -1874,6 +2069,8 @@ func (this *EdbInfoController) EdbInfoAdd() {
 		return
 	}
 
+	subSource := utils.DATA_SUB_SOURCE_EDB
+
 	req.EdbName = strings.Trim(req.EdbName, " ")
 	req.EdbCode = strings.Trim(req.EdbCode, " ")
 
@@ -1925,7 +2122,7 @@ func (this *EdbInfoController) EdbInfoAdd() {
 	}
 
 	// 指标入库
-	edbInfo, err, errMsg, isSendEmail := data.EdbInfoAdd(source, req.ClassifyId, req.EdbCode, req.EdbName, req.Frequency, req.Unit, req.StartDate, req.EndDate, sysUser.AdminId, sysUser.RealName)
+	edbInfo, err, errMsg, isSendEmail := data.EdbInfoAdd(source, subSource, req.ClassifyId, req.EdbCode, req.EdbName, req.Frequency, req.Unit, req.StartDate, req.EndDate, sysUser.AdminId, sysUser.RealName)
 	if err != nil {
 		br.Msg = "保存失败"
 		if errMsg != `` {
@@ -2108,7 +2305,13 @@ func (this *EdbInfoController) EdbInfoEdit() {
 
 	//添加es
 	data.AddOrEditEdbInfoToEs(req.EdbInfoId)
+	// 修改关联的预测指标基础信息
+	go data.ModifyPredictEdbBaseInfoBySourceEdb(edbInfo)
 
+	// 添加钢联指标更新日志
+	if edbInfo.Source == utils.DATA_SOURCE_MYSTEEL_CHEMICAL {
+		go data_stat.AddEdbInfoUpdateLog(req.EdbInfoId, 1, "", sysUser)
+	}
 	br.Ret = 200
 	br.Success = true
 	br.Msg = "保存成功"
@@ -3007,18 +3210,29 @@ func (this *ChartInfoController) EdbInfoData() {
 
 	startDate := this.GetString("StartDate")
 	endDate := this.GetString("EndDate")
-	startDate, endDate = utils.GetDateByDateType(dateType, startDate, endDate)
+	startYear, _ := this.GetInt("StartYear")
 
 	edbInfo, err := data_manage.GetEdbInfoById(edbInfoId)
 	if err != nil {
+		if err.Error() == utils.ErrNoRow() {
+			br.Ret = 200
+			return
+		}
 		br.Msg = "获取失败"
-		br.Msg = "获取失败,Err:" + err.Error()
+		br.ErrMsg = "获取失败,Err:" + err.Error()
 		return
 	}
-	dataList, err := data_manage.GetEdbDataList(edbInfo.Source, edbInfoId, startDate, endDate)
+	maxYear := 0
+	if edbInfo.LatestDate != "" {
+		latestDateT, _ := time.Parse(utils.FormatDate, edbInfo.LatestDate)
+		maxYear = latestDateT.Year()
+	}
+	dataList := make([]*data_manage.EdbDataList, 0)
+	startDate, endDate = utils.GetDateByDateTypeV2(dateType, startDate, endDate, startYear, maxYear)
+	dataList, err = data_manage.GetEdbDataList(edbInfo.Source, edbInfo.SubSource, edbInfoId, startDate, endDate)
 	if err != nil {
 		br.Msg = "获取失败"
-		br.Msg = "获取失败,Err:" + err.Error()
+		br.ErrMsg = "获取失败,Err:" + err.Error()
 		return
 	}
 	fullEdb := new(data_manage.EdbInfoFullClassify)
@@ -3033,7 +3247,6 @@ func (this *ChartInfoController) EdbInfoData() {
 	fullEdb.ClassifyList = classifyList
 	resp.EdbInfo = fullEdb
 	resp.DataList = dataList
-
 	br.Ret = 200
 	br.Success = true
 	br.Msg = "获取成功"
@@ -3475,7 +3688,7 @@ func (this *EdbInfoController) RelationEdbList() {
 
 		dataList := make([]*data_manage.EdbDataList, 0)
 		if v.EdbInfoType == 0 {
-			dataList, err = data_manage.GetEdbDataList(v.Source, v.EdbInfoId, "", "")
+			dataList, err = data_manage.GetEdbDataList(v.Source, v.SubSource, v.EdbInfoId, "", "")
 		} else {
 			_, dataList, _, _, err, _ = data.GetPredictDataListByPredictEdbInfoId(v.EdbInfoId, "", "", false)
 		}
@@ -3743,7 +3956,7 @@ func (this *ChartInfoController) EdbInfoDataTb() {
 		//同比值的计算方式,是需要与去年同期对比,所以如果用户需要某个时间段的数据的话,获取基础数据时,需要往前面推(1年+兼容的日期频度(目前是35天))
 		startDate = startDateTime.AddDate(-1, 0, -35).Format(utils.FormatDate)
 	}
-	tmpDataList, err := data_manage.GetEdbDataList(edbInfo.Source, edbInfoId, startDate, endDate)
+	tmpDataList, err := data_manage.GetEdbDataList(edbInfo.Source, edbInfo.SubSource, edbInfoId, startDate, endDate)
 	if err != nil {
 		br.Msg = "获取失败"
 		br.Msg = "获取失败,Err:" + err.Error()
@@ -4661,3 +4874,283 @@ func (this *EdbInfoController) ChartImageSet() {
 	br.Success = true
 	br.Msg = "保存成功"
 }
+
+// EdbInfoAdd
+// @Title 指标批量保存接口
+// @Description 指标批量保存接口
+// @Param	request	body data_manage.BatchAddEdbInfoReq true "type json string"
+// @Success Ret=200 保存成功
+// @router /edb_info/batch/add [post]
+func (this *EdbInfoController) EdbInfoBatchAdd() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	deleteCache := true
+	cacheKey := "CACHE_EDB_INFO_BATCH_ADD_" + strconv.Itoa(sysUser.AdminId)
+	defer func() {
+		if deleteCache {
+			utils.Rc.Delete(cacheKey)
+		}
+	}()
+	if !utils.Rc.SetNX(cacheKey, 1, 30*time.Second) {
+		deleteCache = false
+		br.Msg = "系统处理中,请稍后重试!"
+		br.ErrMsg = "系统处理中,请稍后重试!" + sysUser.RealName + ";data:" + string(this.Ctx.Input.RequestBody)
+		return
+	}
+	var req data_manage.BatchAddEdbInfoReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	resp := new(data_manage.AddEdbInfoResp)
+
+	var edbNames string
+	for _, v := range req.BatchList {
+		edbNames += "'" + v.EdbName + "',"
+	}
+	edbNames = strings.Trim(edbNames, ",")
+	infoList, err := data_manage.GetEdbInfoByNames(edbNames)
+	if err != nil {
+		br.Msg = "查询指标名称重复错误!"
+		br.ErrMsg = "GetEdbInfoByNames,Err:" + err.Error()
+		return
+	}
+	if len(infoList) > 0 {
+		for _, v := range infoList {
+			resp.ExistEdbName = append(resp.ExistEdbName, v.EdbName)
+		}
+		br.Data = resp
+		br.Msg = "指标名称重复!"
+		br.ErrMsg = "指标名称重复"
+		return
+	}
+
+	for k, v := range req.BatchList {
+		v.EdbName = strings.Trim(v.EdbName, " ")
+		v.EdbCode = strings.Trim(v.EdbCode, " ")
+		v.StockCode = strings.Trim(v.StockCode, " ")
+
+		if v.Source <= 0 {
+			br.Msg = "无效的数据来源"
+			return
+		}
+
+		if v.EdbCode == "" {
+			br.Msg = "指标ID不能为空"
+			return
+		}
+
+		if v.StockCode == "" {
+			br.Msg = "证券代码不能为空"
+			return
+		}
+
+		if v.EdbName == "" {
+			br.Msg = "指标名称不能为空"
+			return
+		}
+
+		if v.Frequency == "" {
+			br.Msg = "频率不能为空"
+			return
+		}
+
+		if v.ClassifyId <= 0 {
+			br.Msg = "请选择分类"
+			return
+		}
+
+		edbInfoItem := new(data_manage.EdbInfo)
+		edbInfoItem.Source = v.Source
+		switch v.Source {
+		case utils.DATA_SOURCE_WIND:
+			edbInfoItem.SourceName = "wind"
+			edbInfoItem.EdbCode = utils.WindDbWsd + v.StockCode + v.EdbCode
+		case utils.DATA_SOURCE_THS:
+			edbInfoItem.SourceName = "ths"
+			edbInfoItem.EdbCode = utils.ThsDs + v.StockCode + v.EdbCode
+		}
+		edbInfoItem.SubSource = 1
+		edbInfoItem.SubSourceName = "日期序列"
+		edbInfoItem.EdbName = v.EdbName
+		edbInfoItem.Frequency = v.Frequency
+		edbInfoItem.Unit = v.Unit
+		edbInfoItem.ClassifyId = v.ClassifyId
+		edbInfoItem.SysUserId = sysUser.AdminId
+		edbInfoItem.SysUserRealName = sysUser.RealName
+		edbInfoItem.IndicatorCode = v.EdbCode
+		edbInfoItem.StockCode = v.StockCode
+
+		// 指标入库
+		edbInfo, err, errMsg, isSendEmail := data.EdbInfoWsdAdd(edbInfoItem)
+		if err != nil {
+			br.Msg = "保存失败"
+			if errMsg != `` {
+				br.Msg = errMsg
+			}
+			br.ErrMsg = err.Error()
+			br.IsSendEmail = isSendEmail
+			return
+		}
+		//新增操作日志
+		{
+			edbLog := new(data_manage.EdbInfoLog)
+			edbLog.EdbInfoId = edbInfo.EdbInfoId
+			edbLog.SourceName = edbInfo.SourceName
+			edbLog.Source = edbInfo.Source
+			edbLog.EdbCode = edbInfo.EdbCode
+			edbLog.EdbName = edbInfo.EdbName
+			edbLog.ClassifyId = edbInfo.ClassifyId
+			edbLog.SysUserId = sysUser.AdminId
+			edbLog.SysUserRealName = sysUser.RealName
+			edbLog.CreateTime = time.Now()
+			edbLog.Content = string(this.Ctx.Input.RequestBody)
+			edbLog.Status = "新增指标"
+			edbLog.Method = this.Ctx.Input.URI()
+			go data_manage.AddEdbInfoLog(edbLog)
+		}
+
+		if k <= 0 {
+			resp.EdbInfoId = edbInfo.EdbInfoId
+			resp.UniqueCode = edbInfo.UniqueCode
+		}
+	}
+
+	//// 试用平台更新用户累计新增指标数
+	//adminItem, e := system.GetSysAdminById(sysUser.AdminId)
+	//if e != nil {
+	//	br.Msg = "操作失败"
+	//	br.ErrMsg = "获取系统用户数据失败,Err:" + err.Error()
+	//	return
+	//}
+	//if utils.BusinessCode == utils.BusinessCodeSandbox && adminItem.DepartmentName == "ETA试用客户" {
+	//	go func() {
+	//		var r etaTrialService.EtaTrialUserReq
+	//		r.Mobile = adminItem.Mobile
+	//		_, _ = etaTrialService.UpdateUserIndexNum(r)
+	//	}()
+	//}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "保存成功"
+	br.Data = resp
+	br.IsAddLog = true
+}
+
+// EdbInfoExistCheck
+// @Title 新增指标-检验指标是否存在接口
+// @Description 新增指标-检验指标是否存在接口
+// @Param   Source   query   int  true       "来源:1:同花顺,2:wind"
+// @Param   SubSource   query   int  true       "子数据来源:0:经济数据库,1:日期序列"
+// @Param   EdbCode   query   string  false       "指标编码/指标代码"
+// @Param   StockCode   query   string  false       "证券代码"
+// @Success 200 {object} data_manage.EdbInfoExistCheckResp
+// @router /edb_info/exist/check [get]
+func (this *EdbInfoController) EdbInfoExistCheck() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	source, _ := this.GetInt("Source")
+	edbCode := this.GetString("EdbCode")
+	edbCode = strings.Trim(edbCode, "\t")
+	edbCode = strings.Trim(edbCode, " ")
+	edbCode = strings.Replace(edbCode, "\t", "", -1)
+	subSource, _ := this.GetInt("SubSource")
+	stockCode := this.GetString("StockCode")
+
+	if source <= 0 {
+		br.Msg = "无效的数据来源"
+		return
+	}
+
+	if edbCode == "" {
+		br.Msg = "请输入指标ID"
+		return
+	}
+
+	if source != utils.DATA_SOURCE_WIND && source != utils.DATA_SOURCE_THS {
+		br.Msg = "无效的数据来源"
+		return
+	}
+	if subSource != utils.DATA_SUB_SOURCE_DATE {
+		br.Msg = "无效的数据库来源"
+		return
+	}
+
+	var indexCodeArr []string
+	edbCodeArr := strings.Split(edbCode, ",")
+	stockCodeArr := strings.Split(stockCode, ",")
+
+	var prefix string
+	if source == utils.DATA_SOURCE_WIND {
+		prefix = utils.WindDbWsd
+	} else if source == utils.DATA_SOURCE_THS {
+		prefix = utils.ThsDs
+	} else {
+		br.Msg = "来源错误"
+		br.ErrMsg = "来源错误"
+		return
+	}
+	for _, sv := range stockCodeArr {
+		for _, ev := range edbCodeArr {
+			indexCode := prefix + sv + ev
+			indexCodeArr = append(indexCodeArr, indexCode)
+		}
+	}
+	indexList, err := data_manage.GetEdbInfoByEdbCodeList(source, indexCodeArr)
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		br.Msg = "校验指标是否存在失败"
+		br.ErrMsg = "校验指标是否存在失败,Err:" + err.Error()
+		return
+	}
+	var existStockCodeArr []string
+	var existEdbCodeArr []string
+	var existClassifyId []int
+	var existIndexId []int
+
+	for _, indexItem := range indexList {
+		for _, sv := range stockCodeArr {
+			for _, ev := range edbCodeArr {
+				if strings.Contains(indexItem.EdbCode, sv) {
+					existStockCodeArr = append(existStockCodeArr, sv)
+				}
+				if strings.Contains(indexItem.EdbCode, ev) {
+					existEdbCodeArr = append(existEdbCodeArr, ev)
+					existClassifyId = append(existClassifyId, indexItem.ClassifyId)
+					existIndexId = append(existIndexId, indexItem.EdbInfoId)
+				}
+			}
+		}
+	}
+
+	resp := new(data_manage.EdbInfoExistCheckResp)
+	if len(indexList) > 0 {
+		resp.IndexExist = true
+	}
+	resp.ExistEdbCodeArr = existEdbCodeArr
+	resp.ExistStockCodeArr = existStockCodeArr
+	resp.ExistClassifyId = existClassifyId
+	resp.ExistIndexId = existIndexId
+	resp.ExistEdbInfo = indexList
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}

+ 3 - 28
controllers/data_manage/future_good/future_good_chart_classify.go

@@ -5,6 +5,7 @@ import (
 	"eta/eta_mobile/models"
 	"eta/eta_mobile/models/data_manage"
 	"eta/eta_mobile/models/system"
+	"eta/eta_mobile/services/data"
 	"eta/eta_mobile/utils"
 	"fmt"
 )
@@ -52,7 +53,7 @@ func (this *FutureGoodChartClassifyController) ChartClassifyList() {
 			return
 		}
 		// 移除没有权限的图表
-		allNodes := handleNoPermissionChart(resp.AllNodes, noPermissionChartIdMap)
+		allNodes := data.HandleNoPermissionChart(resp.AllNodes, noPermissionChartIdMap)
 		resp.AllNodes = allNodes
 
 		br.Ret = 200
@@ -93,7 +94,7 @@ func (this *FutureGoodChartClassifyController) ChartClassifyList() {
 	}
 
 	// 移除没有权限的图表
-	allNodes := handleNoPermissionChart(rootList, noPermissionChartIdMap)
+	allNodes := data.HandleNoPermissionChart(rootList, noPermissionChartIdMap)
 	resp.AllNodes = allNodes
 
 	br.Ret = 200
@@ -134,29 +135,3 @@ func getChartClassifyListForMe(adminInfo system.Admin, resp *data_manage.ChartCl
 
 	return
 }
-
-// handleNoPermissionChart 图表列表返回,将没有权限的图表移除
-func handleNoPermissionChart(allNodes []*data_manage.ChartClassifyItems, noPermissionChartIdMap map[int]bool) (newAllNodes []*data_manage.ChartClassifyItems) {
-	// 移除没有权限的图表
-	newAllNodes = make([]*data_manage.ChartClassifyItems, 0)
-	for _, node := range allNodes {
-		// 二级分类
-		tmpNodeInfo := *node
-		tmpNodeList := make([]*data_manage.ChartClassifyItems, 0)
-
-		if node.Children != nil {
-			for _, chartInfo := range node.Children {
-				// 如果指标不可见,那么就不返回该指标
-				if _, ok := noPermissionChartIdMap[chartInfo.ChartInfoId]; ok {
-					continue
-				}
-				tmpNodeList = append(tmpNodeList, chartInfo)
-			}
-		}
-
-		tmpNodeInfo.Children = tmpNodeList
-		newAllNodes = append(newAllNodes, &tmpNodeInfo)
-	}
-
-	return
-}

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

@@ -256,7 +256,7 @@ func (this *FutureGoodChartInfoController) ChartInfoSearchByEs() {
 	if keyword != "" {
 		searchList, total, err = data.EsSearchChartInfo(keyword, showSysId, []int{utils.CHART_SOURCE_FUTURE_GOOD}, noPermissionChartIdList, startSize, pageSize)
 	} else {
-		total, searchList, err = data_manage.ChartInfoSearchByEmptyKeyWord(showSysId, []int{utils.CHART_SOURCE_FUTURE_GOOD}, noPermissionChartIdList)
+		total, searchList, err = data_manage.ChartInfoSearchByEmptyKeyWord(showSysId, []int{utils.CHART_SOURCE_FUTURE_GOOD}, noPermissionChartIdList, startSize, pageSize)
 		if err != nil && err.Error() != utils.ErrNoRow() {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取图表信息失败,Err:" + err.Error()
@@ -685,4 +685,4 @@ func (this *FutureGoodChartInfoController) ChartInfoSave() {
 	br.Success = true
 	br.Msg = "保存成功"
 	br.IsAddLog = true
-}
+}

+ 2 - 27
controllers/data_manage/line_equation/line_chart_classify.go

@@ -5,6 +5,7 @@ import (
 	"eta/eta_mobile/models"
 	"eta/eta_mobile/models/data_manage"
 	"eta/eta_mobile/models/system"
+	"eta/eta_mobile/services/data"
 	"eta/eta_mobile/utils"
 )
 
@@ -97,7 +98,7 @@ func (this *LineEquationChartClassifyController) ChartClassifyList() {
 	}
 
 	// 移除没有权限的图表
-	allNodes := handleNoPermissionChart(rootList, noPermissionChartIdMap)
+	allNodes := data.HandleNoPermissionChart(rootList, noPermissionChartIdMap)
 	resp.AllNodes = allNodes
 
 	br.Ret = 200
@@ -139,29 +140,3 @@ func getChartClassifyListForMe(adminInfo system.Admin, resp *data_manage.ChartCl
 
 	return
 }
-
-// handleNoPermissionChart 图表列表返回,将没有权限的图表移除
-func handleNoPermissionChart(allNodes []*data_manage.ChartClassifyItems, noPermissionChartIdMap map[int]bool) (newAllNodes []*data_manage.ChartClassifyItems) {
-	// 移除没有权限的图表
-	newAllNodes = make([]*data_manage.ChartClassifyItems, 0)
-	for _, node := range allNodes {
-		// 二级分类
-		tmpNodeInfo := *node
-		tmpNodeList := make([]*data_manage.ChartClassifyItems, 0)
-
-		if node.Children != nil {
-			for _, chartInfo := range node.Children {
-				// 如果指标不可见,那么就不返回该指标
-				if _, ok := noPermissionChartIdMap[chartInfo.ChartInfoId]; ok {
-					continue
-				}
-				tmpNodeList = append(tmpNodeList, chartInfo)
-			}
-		}
-
-		tmpNodeInfo.Children = tmpNodeList
-		newAllNodes = append(newAllNodes, &tmpNodeInfo)
-	}
-
-	return
-}

+ 1 - 1
controllers/data_manage/line_equation/line_chart_info.go

@@ -264,7 +264,7 @@ func (this *LineEquationChartInfoController) SearchByEs() {
 	if keyword != "" {
 		searchList, total, err = data.EsSearchChartInfo(keyword, showSysId, sourceList, noPermissionChartIdList, startSize, pageSize)
 	} else {
-		total, searchList, err = data_manage.ChartInfoSearchByEmptyKeyWord(showSysId, sourceList, noPermissionChartIdList)
+		total, searchList, err = data_manage.ChartInfoSearchByEmptyKeyWord(showSysId, sourceList, noPermissionChartIdList, startSize, pageSize)
 		if err != nil && err.Error() != utils.ErrNoRow() {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取图表信息失败,Err:" + err.Error()

+ 1 - 1
controllers/data_manage/line_feature/chart_info.go

@@ -548,7 +548,7 @@ func (this *LineFeaturesChartInfoController) SearchByEs() {
 	if keyword != "" {
 		searchList, total, err = data.EsSearchChartInfo(keyword, showSysId, sourceList, noPermissionChartIdList, startSize, pageSize)
 	} else {
-		total, searchList, err = data_manage.ChartInfoSearchByEmptyKeyWord(showSysId, sourceList, noPermissionChartIdList)
+		total, searchList, err = data_manage.ChartInfoSearchByEmptyKeyWord(showSysId, sourceList, noPermissionChartIdList, startSize, pageSize)
 		if err != nil && err.Error() != utils.ErrNoRow() {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取图表信息失败,Err:" + err.Error()

+ 2 - 27
controllers/data_manage/line_feature/classify.go

@@ -5,6 +5,7 @@ import (
 	"eta/eta_mobile/models"
 	"eta/eta_mobile/models/data_manage"
 	"eta/eta_mobile/models/system"
+	"eta/eta_mobile/services/data"
 	"eta/eta_mobile/utils"
 )
 
@@ -97,7 +98,7 @@ func (this *LineFeaturesChartClassifyController) ChartClassifyList() {
 	}
 
 	// 移除没有权限的图表
-	allNodes := handleNoPermissionChart(rootList, noPermissionChartIdMap)
+	allNodes := data.HandleNoPermissionChart(rootList, noPermissionChartIdMap)
 	resp.AllNodes = allNodes
 
 	br.Ret = 200
@@ -139,29 +140,3 @@ func getChartClassifyListForMe(adminInfo system.Admin, resp *data_manage.ChartCl
 
 	return
 }
-
-// handleNoPermissionChart 图表列表返回,将没有权限的图表移除
-func handleNoPermissionChart(allNodes []*data_manage.ChartClassifyItems, noPermissionChartIdMap map[int]bool) (newAllNodes []*data_manage.ChartClassifyItems) {
-	// 移除没有权限的图表
-	newAllNodes = make([]*data_manage.ChartClassifyItems, 0)
-	for _, node := range allNodes {
-		// 二级分类
-		tmpNodeInfo := *node
-		tmpNodeList := make([]*data_manage.ChartClassifyItems, 0)
-
-		if node.Children != nil {
-			for _, chartInfo := range node.Children {
-				// 如果指标不可见,那么就不返回该指标
-				if _, ok := noPermissionChartIdMap[chartInfo.ChartInfoId]; ok {
-					continue
-				}
-				tmpNodeList = append(tmpNodeList, chartInfo)
-			}
-		}
-
-		tmpNodeInfo.Children = tmpNodeList
-		newAllNodes = append(newAllNodes, &tmpNodeInfo)
-	}
-
-	return
-}

+ 6 - 6
controllers/data_manage/predict_edb_info.go

@@ -159,14 +159,14 @@ func (this *PredictEdbInfoController) List() {
 			dataCondition += ` AND edb_info_id=? `
 			dataPars = append(dataPars, sourceEdbInfoItem.EdbInfoId)
 
-			dataCount, err := data_manage.GetEdbDataCountByCondition(dataCondition, dataPars, sourceEdbInfoItem.Source)
+			dataCount, err := data_manage.GetEdbDataCountByCondition(dataCondition, dataPars, sourceEdbInfoItem.Source, sourceEdbInfoItem.SubSource)
 			if err != nil && err.Error() != utils.ErrNoRow() {
 				br.Msg = "获取指标信息失败"
 				br.ErrMsg = "获取指标数据总数失败,Err:" + err.Error()
 				return
 			}
 			page = paging.GetPaging(currentIndex, pageSize, dataCount)
-			dataList, err := data_manage.GetEdbDataListByCondition(dataCondition, dataPars, sourceEdbInfoItem.Source, pageSize, startSize)
+			dataList, err := data_manage.GetEdbDataListByCondition(dataCondition, dataPars, sourceEdbInfoItem.Source, sourceEdbInfoItem.SubSource, pageSize, startSize)
 			if err != nil {
 				br.Msg = "获取指标信息失败"
 				br.ErrMsg = "获取指标数据失败,Err:" + err.Error()
@@ -177,7 +177,7 @@ func (this *PredictEdbInfoController) List() {
 
 		// 第一页才需要 获取预测指标未来的数据
 		if currentIndex == 1 {
-			allDataList, err := data_manage.GetEdbDataList(sourceEdbInfoItem.Source, sourceEdbInfoItem.EdbInfoId, "", "")
+			allDataList, err := data_manage.GetEdbDataList(sourceEdbInfoItem.Source, sourceEdbInfoItem.SubSource, sourceEdbInfoItem.EdbInfoId, "", "")
 			if err != nil {
 				br.Msg = "获取失败"
 				br.Msg = "获取失败,Err:" + err.Error()
@@ -226,14 +226,14 @@ func (this *PredictEdbInfoController) List() {
 			dataCondition += ` AND edb_info_id=? AND data_time <= ? `
 			dataPars = append(dataPars, edbInfoItem.EdbInfoId, edbInfoItem.LatestDate)
 
-			dataCount, err := data_manage.GetEdbDataCountByCondition(dataCondition, dataPars, edbInfoItem.Source)
+			dataCount, err := data_manage.GetEdbDataCountByCondition(dataCondition, dataPars, edbInfoItem.Source, edbInfoItem.SubSource)
 			if err != nil && err.Error() != utils.ErrNoRow() {
 				br.Msg = "获取指标信息失败"
 				br.ErrMsg = "获取指标数据总数失败,Err:" + err.Error()
 				return
 			}
 			page = paging.GetPaging(currentIndex, pageSize, dataCount)
-			dataList, err := data_manage.GetEdbDataListByCondition(dataCondition, dataPars, edbInfoItem.Source, pageSize, startSize)
+			dataList, err := data_manage.GetEdbDataListByCondition(dataCondition, dataPars, edbInfoItem.Source, edbInfoItem.SubSource, pageSize, startSize)
 			if err != nil {
 				br.Msg = "获取指标信息失败"
 				br.ErrMsg = "获取指标数据失败,Err:" + err.Error()
@@ -250,7 +250,7 @@ func (this *PredictEdbInfoController) List() {
 			dataCondition += ` AND edb_info_id=? AND data_time > ? `
 			dataPars = append(dataPars, edbInfoItem.EdbInfoId, edbInfoItem.LatestDate)
 
-			predictDataList, err = data_manage.GetAllEdbDataListByCondition(dataCondition, dataPars, edbInfoItem.Source)
+			predictDataList, err = data_manage.GetAllEdbDataListByCondition(dataCondition, dataPars, edbInfoItem.Source, edbInfoItem.SubSource)
 			if err != nil {
 				br.Msg = "获取指标信息失败"
 				br.ErrMsg = "获取指标数据失败,Err:" + err.Error()

+ 10 - 0
controllers/english_report/report.go

@@ -7,6 +7,7 @@ import (
 	"eta/eta_mobile/models/company"
 	"eta/eta_mobile/services"
 	"eta/eta_mobile/services/alarm_msg"
+	"eta/eta_mobile/services/data"
 	"eta/eta_mobile/utils"
 	"fmt"
 	"github.com/rdlucklib/rdluck_tools/paging"
@@ -893,6 +894,15 @@ func (this *EnglishReportController) PublishReport() {
 			return
 		}
 
+		// 图表刷新状态
+		refreshResult := data.CheckBatchChartRefreshResult("report", vint, 0)
+		if !refreshResult {
+			br.Msg = "图表刷新未完成,请稍后操作"
+			br.ErrMsg = "图表刷新未完成,请稍后操作"
+			br.IsSendEmail = false
+			return
+		}
+
 		var tmpErr error
 
 		if report.Content == "" {

+ 21 - 0
controllers/error.go

@@ -0,0 +1,21 @@
+package controllers
+
+import "eta/eta_mobile/models"
+
+// ErrorController
+// @Description: 该控制器处理页面错误请求
+type ErrorController struct {
+	BaseCommonController
+}
+
+func (c *ErrorController) Error404() {
+	c.Data["content"] = "很抱歉您访问的地址或者方法不存在"
+	//c.TplName = "error/404.html"
+
+	br := new(models.BaseResponse).Init()
+
+	br.Msg = "您访问的资源不存在"
+	br.Ret = 404
+	c.Data["json"] = br
+	c.ServeJSON()
+}

+ 30 - 0
controllers/report.go

@@ -5,6 +5,7 @@ import (
 	"eta/eta_mobile/models"
 	"eta/eta_mobile/services"
 	"eta/eta_mobile/services/alarm_msg"
+	"eta/eta_mobile/services/data"
 	"eta/eta_mobile/utils"
 	"fmt"
 	"github.com/beego/beego/v2/server/web"
@@ -274,6 +275,16 @@ func (this *ReportController) PublishReport() {
 			br.Msg = "报告不存在"
 			return
 		}
+
+		// 图表刷新状态
+		refreshResult := data.CheckBatchChartRefreshResult("report", vint, 0)
+		if !refreshResult {
+			br.Msg = "图表刷新未完成,请稍后操作"
+			br.ErrMsg = "图表刷新未完成,请稍后操作"
+			br.IsSendEmail = false
+			return
+		}
+
 		var publishTime time.Time
 		if report.MsgIsSend == 1 && report.PublishTime != "" { //如果报告曾经发布过,并且已经发送过模版消息,则章节的发布时间为报告的发布时间
 			publishTime, _ = time.ParseInLocation(utils.FormatDateTime, report.PublishTime, time.Local)
@@ -1993,6 +2004,15 @@ func (this *ReportController) PublishDayWeekReportChapter() {
 		return
 	}
 
+	// 图表刷新状态
+	refreshResult := data.CheckBatchChartRefreshResult("report", chapterInfo.ReportId, chapterInfo.ReportChapterId)
+	if !refreshResult {
+		br.Msg = "图表刷新未完成,请稍后操作"
+		br.ErrMsg = "图表刷新未完成,请稍后操作"
+		br.IsSendEmail = false
+		return
+	}
+
 	// 获取规则配置
 	reportChapterTypeRule, err := models.GetReportChapterTypeById(chapterInfo.TypeId)
 	if err != nil {
@@ -2164,6 +2184,16 @@ func (this *ReportController) PublishDayWeekReport() {
 		br.Msg = "该报告已发布"
 		return
 	}
+
+	// 图表刷新状态
+	refreshResult := data.CheckBatchChartRefreshResult("report", reportId, 0)
+	if !refreshResult {
+		br.Msg = "图表刷新未完成,请稍后操作"
+		br.ErrMsg = "图表刷新未完成,请稍后操作"
+		br.IsSendEmail = false
+		return
+	}
+	
 	tips, err := services.PublishDayWeekReport(reportId)
 	if err != nil {
 		br.Msg = "发布失败"

+ 2 - 2
controllers/sandbox/sandbox.go

@@ -54,7 +54,7 @@ func (this *SandboxController) ListByQuote() {
 	}
 
 	if keyword != "" {
-		condition += ` AND  ( a.name LIKE '%` + keyword + `%'  OR  b.name LIKE '%` + keyword + `%' OR  a.chart_permission_name LIKE '%` + keyword + `%' )`
+		condition += ` AND  ( a.name LIKE '%` + keyword + `%' OR  a.chart_permission_name LIKE '%` + keyword + `%' )`
 	}
 
 	//获取指标信息
@@ -67,7 +67,7 @@ func (this *SandboxController) ListByQuote() {
 	}
 
 	if list == nil || (err != nil && err.Error() == utils.ErrNoRow()) {
-		list = make([]*sandbox.SandboxListItem, 0)
+		list = make([]*sandbox.Sandbox, 0)
 	}
 
 	page := paging.GetPaging(currentIndex, pageSize, total)

+ 42 - 24
controllers/user_login.go

@@ -241,7 +241,7 @@ func (this *UserLoginController) GetVerifyCode() {
 func (this *UserLoginController) Login() {
 	br := new(models.BaseResponse).Init()
 	defer func() {
-		if br.ErrMsg != "" {
+		if br.ErrMsg == "" {
 			br.IsSendEmail = false
 		}
 		this.Data["json"] = br
@@ -256,6 +256,7 @@ func (this *UserLoginController) Login() {
 		Mobile     string `description:"手机号"`
 		Email      string `description:"邮箱"`
 		VerifyCode string `description:"验证码"`
+		ReqTime    string `description:"登录时间戳"`
 	}
 	var req UserLoginReq
 	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
@@ -307,38 +308,55 @@ func (this *UserLoginController) Login() {
 			return
 		}
 
-		// 账号密码校验
+		// 查询账号信息
 		errPassKey := fmt.Sprint(utils.CACHE_LOGIN_ERR_PASS, req.Username)
-		accountUser, e := system.CheckSysUser(req.Username, req.Password)
+		accountUser, e := system.GetSysUserByAdminName(req.Username)
 		if e != nil {
 			br.Ret = models.BaseRespCodeLoginErr
-			if e.Error() == utils.ErrNoRow() {
-				br.Msg = "登录失败, 账号或密码错误"
-				if isAbnormal != "" {
-					return
-				}
-				// 错误密码计数, 超过6次标记异常
-				if !utils.Rc.IsExist(errPassKey) {
-					_ = utils.Rc.Put(errPassKey, 1, utils.GetTodayLastSecond())
-					return
-				}
-				errNum, _ := utils.Rc.RedisInt(errPassKey)
-				errNum += 1
-				if errNum >= 6 {
-					br.Ret = models.BaseRespCodeAbnormalLogin
-					br.Msg = "账号异常, 请进行手机号/邮箱校验"
-					// 标记异常登录, 重置计数
-					_ = utils.Rc.Put(abnormalKey, "true", utils.GetTodayLastSecond())
-					_ = utils.Rc.Delete(errPassKey)
-					return
-				}
+			br.Msg = "登录失败, 账号或密码错误"
+			// 账号查询异常均进行标记, 避免一直尝试进行登录
+			if !utils.Rc.IsExist(errPassKey) {
+				_ = utils.Rc.Put(errPassKey, 1, utils.GetTodayLastSecond())
+				return
+			}
+			errNum, _ := utils.Rc.RedisInt(errPassKey)
+			errNum += 1
+			if errNum < 6 {
 				_ = utils.Rc.Put(errPassKey, errNum, utils.GetTodayLastSecond())
 				return
 			}
+			// 标记异常登录, 重置计数
+			br.Ret = models.BaseRespCodeAbnormalLogin
+			br.Msg = "账号异常, 请进行手机号/邮箱校验"
+			_ = utils.Rc.Put(abnormalKey, "true", utils.GetTodayLastSecond())
+			_ = utils.Rc.Delete(errPassKey)
+			return
+		}
+
+		// 账号密码校验
+		dbPass := utils.MD5(fmt.Sprintf("%s%s%s", accountUser.Password, utils.UserLoginSalt, req.ReqTime))
+		if req.Password != dbPass {
+			br.Ret = models.BaseRespCodeLoginErr
 			br.Msg = "登录失败, 账号或密码错误"
-			br.ErrMsg = "登录失败, Err:" + e.Error()
+			// 错误密码计数, 超过6次标记异常
+			if !utils.Rc.IsExist(errPassKey) {
+				_ = utils.Rc.Put(errPassKey, 1, utils.GetTodayLastSecond())
+				return
+			}
+			errNum, _ := utils.Rc.RedisInt(errPassKey)
+			errNum += 1
+			if errNum < 6 {
+				_ = utils.Rc.Put(errPassKey, errNum, utils.GetTodayLastSecond())
+				return
+			}
+			// 标记异常登录, 重置计数
+			br.Ret = models.BaseRespCodeAbnormalLogin
+			br.Msg = "账号异常, 请进行手机号/邮箱校验"
+			_ = utils.Rc.Put(abnormalKey, "true", utils.GetTodayLastSecond())
+			_ = utils.Rc.Delete(errPassKey)
 			return
 		}
+
 		if accountUser.Enabled == 0 {
 			br.Msg = "您的账号已被禁用, 如需登录, 请联系管理员"
 			br.ErrMsg = fmt.Sprintf("账号已被禁用, 登录账号: %s, 账户名称: %s", accountUser.AdminName, accountUser.RealName)

BIN
eta_mobile.exe


+ 4 - 0
main.go

@@ -1,6 +1,7 @@
 package main
 
 import (
+	"eta/eta_mobile/controllers"
 	"eta/eta_mobile/services/alarm_msg"
 	"fmt"
 	"runtime"
@@ -20,6 +21,9 @@ func main() {
 		web.BConfig.WebConfig.StaticDir["/swagger"] = "swagger"
 	}
 
+	// 异常处理
+	web.ErrorController(&controllers.ErrorController{})
+
 	web.BConfig.RecoverFunc = Recover
 	web.Run()
 }

+ 15 - 0
models/data_manage/chart_classify.go

@@ -1,6 +1,7 @@
 package data_manage
 
 import (
+	"eta/eta_mobile/utils"
 	"fmt"
 	"github.com/beego/beego/v2/client/orm"
 	"time"
@@ -268,3 +269,17 @@ func GetSecondaryChartClassifyWithSort() (items []*ChartClassify, err error) {
 	_, err = o.Raw(sql).QueryRows(&items)
 	return
 }
+
+// GetCrossVarietyChartClassifyBySysUserId
+// @Description: 根据创建人获取跨品种分析的分类
+// @author: Roc
+// @datetime 2023-11-24 14:05:43
+// @param sysUserId int
+// @return item *ChartClassify
+// @return err error
+func GetCrossVarietyChartClassifyBySysUserId(sysUserId int) (item *ChartClassify, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT * FROM chart_classify WHERE source = ? AND sys_user_id=?`
+	err = o.Raw(sql, utils.CHART_SOURCE_CROSS_HEDGING, sysUserId).QueryRow(&item)
+	return
+}

+ 7 - 7
models/data_manage/chart_edb_mapping.go

@@ -36,7 +36,7 @@ func AddChartEdbMapping(items []*ChartEdbMapping) (err error) {
 
 func GetChartEdbMappingList(chartInfoId int) (list []*ChartEdbInfoMapping, err error) {
 	o := orm.NewOrmUsingDB("data")
-	sql := ` SELECT a.*,b.source_name,b.source,b.classify_id,b.edb_code,b.edb_name,b.edb_name_en,b.frequency,b.unit,b.unit_en,b.start_date,b.end_date,b.modify_time,b.latest_date,b.latest_value,b.unique_code,b.edb_info_type AS edb_info_category_type,b.edb_type
+	sql := ` SELECT a.*,b.source_name,b.source,b.sub_source,b.classify_id,b.edb_code,b.edb_name,b.edb_name_en,b.frequency,b.unit,b.unit_en,b.start_date,b.end_date,b.modify_time,b.latest_date,b.latest_value,b.unique_code,b.edb_info_type AS edb_info_category_type,b.edb_type
              FROM chart_edb_mapping AS a
 			 INNER JOIN edb_info AS b ON a.edb_info_id=b.edb_info_id
 			 WHERE chart_info_id=? 
@@ -47,7 +47,7 @@ func GetChartEdbMappingList(chartInfoId int) (list []*ChartEdbInfoMapping, err e
 
 func GetChartEdbMappingListByChartInfoIds(chartInfoIds string) (list []*ChartEdbInfoMapping, err error) {
 	o := orm.NewOrmUsingDB("data")
-	sql := ` SELECT a.*,b.source_name,b.source,b.edb_code,b.edb_name,b.edb_name_en,b.frequency,b.unit,b.unit_en,b.start_date,b.end_date,b.modify_time,b.latest_date,b.latest_value,b.unique_code,b.edb_info_type AS edb_info_category_type,b.edb_type
+	sql := ` SELECT a.*,b.source_name,b.source,b.sub_source,b.edb_code,b.edb_name,b.edb_name_en,b.frequency,b.unit,b.unit_en,b.start_date,b.end_date,b.modify_time,b.latest_date,b.latest_value,b.unique_code,b.edb_info_type AS edb_info_category_type,b.edb_type
              FROM chart_edb_mapping AS a
 			 INNER JOIN edb_info AS b ON a.edb_info_id=b.edb_info_id
 			 WHERE chart_info_id in (` + chartInfoIds + `) 
@@ -58,7 +58,7 @@ func GetChartEdbMappingListByChartInfoIds(chartInfoIds string) (list []*ChartEdb
 
 func GetChartEdbMappingListByEdbInfoId(edbInfoStr string) (list []*ChartEdbInfoMapping, err error) {
 	o := orm.NewOrmUsingDB("data")
-	sql := ` SELECT edb_info_id,source_name,source,edb_code,edb_name,edb_name_en,frequency,unit,unit_en,start_date,end_date,modify_time,latest_date,latest_value,unique_code,edb_info_type AS edb_info_category_type,max_value,min_value,edb_type
+	sql := ` SELECT edb_info_id,source_name,source,sub_source,edb_code,edb_name,edb_name_en,frequency,unit,unit_en,start_date,end_date,modify_time,latest_date,latest_value,unique_code,edb_info_type AS edb_info_category_type,max_value,min_value,edb_type
              FROM edb_info
 			 WHERE edb_info_id IN(` + edbInfoStr + `)
 			ORDER BY FIELD(edb_info_id,` + edbInfoStr + `)
@@ -74,7 +74,7 @@ func GetChartEdbMappingListByEdbInfoIdList(edbIdList []int) (list []*ChartEdbInf
 		return
 	}
 	o := orm.NewOrmUsingDB("data")
-	sql := ` SELECT edb_info_id,source_name,source,edb_code,edb_name,edb_name_en,frequency,unit,unit_en,start_date,end_date,modify_time,latest_date,latest_value,unique_code,edb_info_type AS edb_info_category_type,max_value,min_value,edb_type
+	sql := ` SELECT edb_info_id,source_name,source,sub_source,edb_code,edb_name,edb_name_en,frequency,unit,unit_en,start_date,end_date,modify_time,latest_date,latest_value,unique_code,edb_info_type AS edb_info_category_type,max_value,min_value,edb_type,sub_source,sub_source_name,indicator_code,stock_code
              FROM edb_info
 			 WHERE edb_info_id IN(` + utils.GetOrmInReplace(num) + `)
 			ORDER BY FIELD(edb_info_id,` + utils.GetOrmInReplace(num) + `)
@@ -90,7 +90,7 @@ func GetChartEdbMappingListByIdList(chartInfoIdList []int) (list []*ChartEdbInfo
 		return
 	}
 	o := orm.NewOrmUsingDB("data")
-	sql := ` SELECT a.*,b.source_name,b.source,b.edb_code,b.edb_name,b.edb_name_en,b.frequency,b.unit,b.unit_en,b.start_date,b.end_date,b.modify_time,b.latest_date,b.latest_value,b.unique_code,b.edb_info_type,b.edb_type AS edb_info_category_type
+	sql := ` SELECT a.*,b.source_name,b.source,b.sub_source,b.edb_code,b.edb_name,b.edb_name_en,b.frequency,b.unit,b.unit_en,b.start_date,b.end_date,b.modify_time,b.latest_date,b.latest_value,b.unique_code,b.edb_info_type,b.edb_type AS edb_info_category_type
              FROM chart_edb_mapping AS a
 			 INNER JOIN edb_info AS b ON a.edb_info_id=b.edb_info_id
 			 WHERE chart_info_id in (` + utils.GetOrmInReplace(num) + `) 
@@ -134,7 +134,7 @@ func GetEtaEdbChartEdbMapping(chartInfoId int) (item *ChartEdbInfoMapping, err e
 	o := orm.NewOrmUsingDB("data")
 	aField := `a.chart_edb_mapping_id,a.chart_info_id,a.edb_info_id,a.create_time,a.modify_time,a.unique_code,a.max_data,a.min_data,a.is_order,a.is_axis,a.edb_info_type,a.lead_value,a.lead_unit,a.chart_style,a.chart_color,a.predict_chart_color,a.chart_width,a.source as mapping_source`
 
-	sql := ` SELECT ` + aField + `,b.source_name,b.source,b.edb_code,b.edb_name,b.edb_name_en,b.frequency,b.unit,b.unit_en,b.start_date,b.end_date,b.modify_time,b.latest_date,b.latest_value,b.unique_code,b.edb_info_type AS edb_info_category_type
+	sql := ` SELECT ` + aField + `,b.source_name,b.source,b.sub_source,b.edb_code,b.edb_name,b.edb_name_en,b.frequency,b.unit,b.unit_en,b.start_date,b.end_date,b.modify_time,b.latest_date,b.latest_value,b.unique_code,b.edb_info_type AS edb_info_category_type
              FROM chart_edb_mapping AS a
 			 INNER JOIN edb_info AS b ON a.edb_info_id=b.edb_info_id
 			 WHERE a.chart_info_id=? AND a.source = ?
@@ -182,7 +182,7 @@ func GetChartEdbMappingListV2(chartInfoId int) (list []*ChartEdbInfoMapping, err
 // GetChartEdbMappingByEdbInfoId 根据指标id获取edb_mapping
 func GetChartEdbMappingByEdbInfoId(edbInfoId int) (item *ChartEdbInfoMapping, err error) {
 	o := orm.NewOrmUsingDB("data")
-	sql := ` SELECT edb_info_id,source_name,classify_id,source,edb_code,edb_name,edb_name_en,frequency,unit,unit_en,start_date,end_date,modify_time,latest_date,latest_value,unique_code,edb_info_type AS edb_info_category_type,max_value,min_value
+	sql := ` SELECT edb_info_id,source_name,classify_id,source,sub_source,edb_code,edb_name,edb_name_en,frequency,unit,unit_en,start_date,end_date,modify_time,latest_date,latest_value,unique_code,edb_info_type AS edb_info_category_type,max_value,min_value
              FROM edb_info
 			 WHERE edb_info_id = ? limit 1`
 	err = o.Raw(sql, edbInfoId).QueryRow(&item)

+ 38 - 19
models/data_manage/chart_info.go

@@ -322,8 +322,8 @@ type EdbDataList struct {
 	Value         float64 `description:"数据值"`
 }
 
-func GetEdbDataList(source, endInfoId int, startDate, endDate string) (list []*EdbDataList, err error) {
-	tableName := GetEdbDataTableName(source)
+func GetEdbDataList(source, subSource, endInfoId int, startDate, endDate string) (list []*EdbDataList, err error) {
+	tableName := GetEdbDataTableName(source, subSource)
 	if tableName == "" {
 		err = errors.New("无效的渠道:" + strconv.Itoa(source))
 		list = make([]*EdbDataList, 0)
@@ -355,8 +355,8 @@ type EdbDataListByUniqueCode struct {
 	Value         float64 `description:"数据值"`
 }
 
-func GetEdbDataListByByUniqueCode(source, endInfoId int, startDate, endDate string) (list []*EdbDataListByUniqueCode, err error) {
-	tableName := GetEdbDataTableName(source)
+func GetEdbDataListByByUniqueCode(source, subSource, endInfoId int, startDate, endDate string) (list []*EdbDataListByUniqueCode, err error) {
+	tableName := GetEdbDataTableName(source, subSource)
 	if tableName == "" {
 		err = errors.New("无效的渠道:" + strconv.Itoa(source))
 		list = make([]*EdbDataListByUniqueCode, 0)
@@ -389,8 +389,8 @@ func GetEdbDataLunarList(endInfoId int, startDate, endDate string) (list []*EdbD
 	return
 }
 
-func GetEdbDataListMinAndMax(source, endInfoId int, startDate, endDate string) (min_data, max_data float64, err error) {
-	tableName := GetEdbDataTableName(source)
+func GetEdbDataListMinAndMax(source, subSource, endInfoId int, startDate, endDate string) (min_data, max_data float64, err error) {
+	tableName := GetEdbDataTableName(source, subSource)
 	sql := `SELECT min(value) AS min_data,max(value) AS max_data FROM %s WHERE edb_info_id=? `
 	var pars []interface{}
 	var condition string
@@ -460,6 +460,10 @@ type ChartEdbInfoMapping struct {
 	MappingSource       int    `description:"1:ETA图库;2:商品价格曲线"`
 	RegionType          string `description:"交易所来源,海外还是国内" json:"-"`
 	ClassifyId          int    `description:"分类id"`
+	SubSource           int    `description:"子数据来源:0:经济数据库,1:日期序列"`
+	SubSourceName       string `description:"子数据来源名称"`
+	IndicatorCode       string `description:"指标代码"`
+	StockCode           string `description:"证券代码"`
 }
 
 type QuarterData struct {
@@ -1026,8 +1030,8 @@ func EditChartEnInfoAndEdbEnInfo(req *EditChartEnInfoReq) (err error) {
 	return
 }
 
-func ModifyEdbDatadTimestamp(source, edbDataId int, dataTimestamp int64) (err error) {
-	tableName := GetEdbDataTableName(source)
+func ModifyEdbDatadTimestamp(source, subSource, edbDataId int, dataTimestamp int64) (err error) {
+	tableName := GetEdbDataTableName(source, subSource)
 	sql := `UPDATE %s SET data_timestamp=? WHERE edb_data_id=? `
 	sql = fmt.Sprintf(sql, tableName)
 	o := orm.NewOrmUsingDB("data")
@@ -1104,27 +1108,39 @@ func ChartInfoSearchByKeyWord(KeyWord string, showSysId int) (searchList []*Char
 }
 
 // ChartInfoSearchByEmptyKeyWord 没有关键字的时候获取默认100条数据
-func ChartInfoSearchByEmptyKeyWord(showSysId int, sourceList []int, noPermissionChartIdList []int) (total int64, searchList []*ChartInfo, err error) {
+func ChartInfoSearchByEmptyKeyWord(showSysId int, sourceList []int, noPermissionChartIdList []int, startSize, pageSize int) (total int64, searchList []*ChartInfo, err error) {
 	num := len(sourceList)
 	o := orm.NewOrmUsingDB("data")
-	sql := ` SELECT * FROM chart_info WHERE 1=1 AND source in (` + utils.GetOrmInReplace(num) + `)`
 
-	var pars []interface{}
-	pars = append(pars, sourceList)
+	baseSql := `  FROM chart_info WHERE 1=1 AND source in (` + utils.GetOrmInReplace(num) + `)`
+
+	var basePars []interface{}
+	basePars = append(basePars, sourceList)
 
 	if showSysId > 0 {
-		sql += ` AND sys_user_id = ? `
-		pars = append(pars, showSysId)
+		baseSql += ` AND sys_user_id = ? `
+		basePars = append(basePars, showSysId)
 	}
 
 	lenNoPermissionChartIdList := len(noPermissionChartIdList)
 	if lenNoPermissionChartIdList > 0 {
-		sql += ` AND chart_info_id not in (` + utils.GetOrmInReplace(lenNoPermissionChartIdList) + `) `
-		pars = append(pars, noPermissionChartIdList)
+		baseSql += ` AND chart_info_id not in (` + utils.GetOrmInReplace(lenNoPermissionChartIdList) + `) `
+		basePars = append(basePars, noPermissionChartIdList)
+	}
+
+	// 查找数量
+	totalSql := " SELECT count(1) as total " + baseSql
+	err = o.Raw(totalSql, basePars).QueryRow(&total)
+	if err != nil {
+		return
 	}
 
-	sql += ` ORDER BY create_time DESC LIMIT 100 `
-	total, err = o.Raw(sql, pars).QueryRows(&searchList)
+	// 查找列表数据
+	sql := " SELECT *  " + baseSql + ` ORDER BY create_time DESC LIMIT ?,? `
+	basePars = append(basePars, startSize, pageSize)
+
+	_, err = o.Raw(sql, basePars).QueryRows(&searchList)
+
 	return
 }
 
@@ -1342,7 +1358,10 @@ func GetChartInfoByClassifyIdAndName(classifyId int, chartName string) (item *Ch
 
 // BatchChartRefreshReq 批量刷新图表请求
 type BatchChartRefreshReq struct {
-	ChartInfoCode []string `description:"图表编码数组"`
+	ChartInfoCode   []string `description:"图表编码数组"`
+	ReportId        int      `description:"报告id"`
+	ReportChapterId int      `description:"报告章节id"`
+	Source          string   `description:"来源,枚举值:report、english_report、smart_report"`
 }
 
 // GetChartInfoListByUniqueCodeSlice 根据图表编码获取图表列表数据

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

@@ -0,0 +1,247 @@
+package cross_variety
+
+import (
+	"eta/eta_mobile/models/data_manage"
+	"eta/eta_mobile/models/data_manage/cross_variety/request"
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
+	"strings"
+	"time"
+)
+
+// ChartInfoCrossVariety
+// @Description: 跨品种分析配置表
+type ChartInfoCrossVariety struct {
+	Id             int       `orm:"column(id);pk"`
+	ChartInfoId    int       `description:"图表id"`
+	ChartXTagId    int       `description:"X轴的标签ID"`
+	ChartYTagId    int       `description:"X轴的标签ID"`
+	CalculateValue int       `description:"计算窗口"`
+	CalculateUnit  string    `description:"计算频度"`
+	ModifyTime     time.Time `description:"修改时间"`
+	CreateTime     time.Time `description:"创建时间"`
+}
+
+// GetCountChartByTagId
+// @Description: 根据标签id获取引用该标签的图表数量
+// @author: Roc
+// @datetime 2023-11-27 10:41:46
+// @param tagId int
+// @return total int64
+// @return err error
+func GetCountChartByTagId(tagId int) (total int64, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT count(1) total FROM chart_info AS a JOIN
+    chart_info_cross_variety AS b on a.chart_info_id = b.chart_info_id 
+    WHERE b.chart_x_tag_id = ? or b.chart_y_tag_id=?`
+	err = o.Raw(sql, tagId, tagId).QueryRow(&total)
+
+	return
+}
+
+// GetChartInfoCrossVarietyByChartInfoId
+// @Description: 根据图表id获取跨品种分析配置信息
+// @author: Roc
+// @datetime 2023-11-24 14:34:50
+// @param id int
+// @return item *ChartInfoCrossVariety
+// @return err error
+func GetChartInfoCrossVarietyByChartInfoId(id int) (item *ChartInfoCrossVariety, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT * FROM chart_info_cross_variety WHERE chart_info_id = ?`
+	err = o.Raw(sql, id).QueryRow(&item)
+
+	return
+}
+
+// CreateChart
+// @Description: 新增跨品种图表
+// @author: Roc
+// @datetime 2023-11-24 14:27:31
+// @param chartInfo *data_manage.ChartInfo
+// @param classify *data_manage.ChartClassify
+// @param chartVarietyMappingList []*ChartVarietyMapping
+// @param chartInfoCrossVariety *ChartInfoCrossVariety
+// @return chartInfoId int
+// @return err error
+func CreateChart(chartInfo *data_manage.ChartInfo, classify *data_manage.ChartClassify, chartVarietyMappingList []*ChartVarietyMapping, chartInfoCrossVariety *ChartInfoCrossVariety) (chartInfoId int, err error) {
+	o := orm.NewOrmUsingDB("data")
+	tx, err := o.Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = tx.Rollback()
+		} else {
+			_ = tx.Commit()
+		}
+	}()
+
+	// 判断是否分类已存在,不存在的话,先添加分类
+	if classify.ChartClassifyId <= 0 {
+		newId, tmpErr := tx.Insert(classify)
+		if tmpErr != nil {
+			err = tmpErr
+			return
+		}
+		classify.ChartClassifyId = int(newId)
+	}
+
+	// 新增图表信息
+	chartInfo.ChartClassifyId = classify.ChartClassifyId
+	newId, err := tx.Insert(chartInfo)
+	if err != nil {
+		return
+	}
+	// 品种列表
+	chartInfo.ChartInfoId = int(newId)
+	chartInfoId = int(newId)
+
+	if len(chartVarietyMappingList) > 0 {
+		for i := range chartVarietyMappingList {
+			chartVarietyMappingList[i].ChartInfoId = chartInfoId
+		}
+		_, err = tx.InsertMulti(len(chartVarietyMappingList), chartVarietyMappingList)
+		if err != nil {
+			return
+		}
+	}
+
+	// 图表配置
+	chartInfoCrossVariety.ChartInfoId = chartInfoId
+	if _, err = tx.Insert(chartInfoCrossVariety); err != nil {
+		return
+	}
+
+	return
+}
+
+// EditChart 修改相关性图表的 图表与指标 的关系
+func EditChart(chartInfo *data_manage.ChartInfo, chartVarietyMappingList []*ChartVarietyMapping, chartInfoCrossVariety *ChartInfoCrossVariety, chartUpdateCols, chartInfoCrossVarietyUpdateCols []string) (err error) {
+	o := orm.NewOrmUsingDB("data")
+	to, err := o.Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = to.Rollback()
+		} else {
+			_ = to.Commit()
+		}
+	}()
+
+	// 更新图表信息
+	_, err = to.Update(chartInfo, chartUpdateCols...)
+	if err != nil {
+		fmt.Println("UPDATE  chart_info Err:", err.Error())
+		return err
+	}
+
+	// 查找现有的品种列表
+	currVarietyMappingList := make([]*ChartVarietyMapping, 0)
+	sql := `SELECT * FROM chart_variety_mapping WHERE chart_info_id = ? `
+	_, err = to.Raw(sql, chartInfo.ChartInfoId).QueryRows(&currVarietyMappingList)
+	if err != nil {
+		return
+	}
+
+	currVarietyMap := make(map[int]*ChartVarietyMapping)
+	for _, v := range currVarietyMappingList {
+		currVarietyMap[v.ChartVarietyId] = v
+	}
+
+	// 待添加的品种列表
+	addVarietyMappingList := make([]*ChartVarietyMapping, 0)
+
+	for i := range chartVarietyMappingList {
+		_, ok := currVarietyMap[i]
+		if !ok {
+			// 如果不存在,那么就添加
+			chartVarietyMappingList[i].ChartInfoId = chartInfo.ChartInfoId
+			addVarietyMappingList = append(addVarietyMappingList, chartVarietyMappingList[i])
+		} else {
+			// 如果存在那么就移除
+			delete(currVarietyMap, i)
+		}
+	}
+
+	// 添加品种
+	if len(addVarietyMappingList) > 0 {
+		_, err = to.InsertMulti(len(addVarietyMappingList), addVarietyMappingList)
+		if err != nil {
+			return
+		}
+	}
+
+	// 删除不存在的品种
+	if len(currVarietyMap) > 0 {
+		idStrList := make([]string, 0)
+		for id, _ := range currVarietyMap {
+			idStrList = append(idStrList, fmt.Sprint(id))
+		}
+		removeIdStr := strings.Join(idStrList, `,`)
+		sql = fmt.Sprintf(` DELETE FROM chart_variety_mapping WHERE id in (%s) `, removeIdStr)
+		_, err = to.Raw(sql).Exec()
+		if err != nil {
+			return
+		}
+	}
+
+	// 跨品种分析图表配置
+	_, err = to.Update(chartInfoCrossVariety, chartInfoCrossVarietyUpdateCols...)
+
+	return
+}
+
+// EditChartEn
+// @Description: 修改英文名称
+// @author: Roc
+// @datetime 2023-11-28 21:17:27
+// @param chartInfo *data_manage.ChartInfo
+// @param req request.EditChartEnInfoReq
+// @return err error
+func EditChartEn(chartInfo *data_manage.ChartInfo, req request.EditChartEnInfoReq) (err error) {
+	o := orm.NewOrmUsingDB("data")
+	to, err := o.Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = to.Rollback()
+		} else {
+			_ = to.Commit()
+		}
+	}()
+
+	// 更新图表信息
+	chartInfo.ChartNameEn = req.ChartNameEn
+	chartInfo.ModifyTime = time.Now().Local()
+	_, err = to.Update(chartInfo, "ChartNameEn", "ModifyTime")
+	if err != nil {
+		fmt.Println("UPDATE  chart_info Err:", err.Error())
+		return err
+	}
+
+	// 更新标签英文名
+	for _, v := range req.TagList {
+		sql := `UPDATE chart_tag SET chart_tag_name_en = ?,modify_time= NOW() WHERE chart_tag_id = ? `
+		_, err = o.Raw(sql, v.TagNameEn, v.ChartTagId).Exec()
+		if err != nil {
+			return
+		}
+	}
+
+	// 更新品种英文名
+	for _, v := range req.VarietyList {
+		sql := `UPDATE chart_variety SET chart_variety_name_en = ?,modify_time= NOW() WHERE chart_variety_id = ? `
+		_, err = o.Raw(sql, v.VarietyNameEn, v.ChartVarietyId).Exec()
+		if err != nil {
+			return
+		}
+	}
+
+	return
+}

+ 148 - 0
models/data_manage/cross_variety/chart_tag.go

@@ -0,0 +1,148 @@
+package cross_variety
+
+import (
+	"eta/eta_mobile/utils"
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+// ChartTag
+// @Description: chart_tag 图表标签表
+type ChartTag struct {
+	ChartTagId      int       `orm:"column(chart_tag_id);pk"`
+	ChartTagName    string    `description:"标签名称"`
+	ChartTagNameEn  string    `description:"标签名称(英文)"`
+	SysUserId       int       `description:"创建人id"`
+	SysUserRealName string    `description:"创建人姓名"`
+	ModifyTime      time.Time `description:"修改时间"`
+	CreateTime      time.Time `description:"创建时间"`
+}
+
+// GetTagById
+// @Description: 根据标签id获取标签详情
+// @author: Roc
+// @datetime 2023-11-21 14:55:31
+// @param id int
+// @return item *ChartTag
+// @return err error
+func GetTagById(id int) (item *ChartTag, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT * FROM chart_tag WHERE chart_tag_id = ?`
+	err = o.Raw(sql, id).QueryRow(&item)
+
+	return
+}
+
+// GetTagByName
+// @Description: 根据标签名称获取标签详情
+// @author: Roc
+// @datetime 2023-11-21 14:55:20
+// @param name string
+// @return item *ChartTag
+// @return err error
+func GetTagByName(name string) (item *ChartTag, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT * FROM chart_tag WHERE chart_tag_name = ?`
+	err = o.Raw(sql, name).QueryRow(&item)
+
+	return
+}
+
+// AddTag
+// @Description: 添加标签
+// @author: Roc
+// @datetime 2023-11-21 14:52:56
+// @param item *ChartTag
+// @return err error
+func AddTag(item *ChartTag) (err error) {
+	o := orm.NewOrmUsingDB("data")
+	lastId, err := o.Insert(item)
+	if err != nil {
+		return
+	}
+
+	item.ChartTagId = int(lastId)
+
+	return
+}
+
+// GetTagList
+// @Description: 获取所有标签列表
+// @author: Roc
+// @datetime 2023-11-22 10:44:35
+// @return items []*ChartTag
+// @return err error
+func GetTagList() (items []*ChartTag, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT * FROM chart_tag WHERE 1 = 1 `
+	_, err = o.Raw(sql).QueryRows(&items)
+
+	return
+}
+
+// Update
+// @Description: 更新标签
+// @author: Roc
+// @receiver item
+// @datetime 2023-11-21 15:15:17
+// @param updateColList []string
+// @return err error
+func (item *ChartTag) Update(updateColList []string) (err error) {
+	to := orm.NewOrmUsingDB("data")
+	_, err = to.Update(item, updateColList...)
+
+	return
+}
+
+// Delete 删除
+func (item *ChartTag) Delete() (err error) {
+	o := orm.NewOrmUsingDB("data")
+	_, err = o.Delete(item)
+	return
+}
+
+// GetTagListByIdList
+// @Description: 根据ID列表获取标签列表
+// @author: Roc
+// @datetime 2023-11-23 17:56:39
+// @param idList []int
+// @return items []*ChartTag
+// @return err error
+func GetTagListByIdList(idList []int) (items []*ChartTag, err error) {
+	num := len(idList)
+	if num <= 0 {
+		return
+	}
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT * FROM chart_tag WHERE 1 = 1 AND chart_tag_id in (` + utils.GetOrmInReplace(num) + `)`
+	_, err = o.Raw(sql, idList).QueryRows(&items)
+
+	return
+}
+
+// ChartTagItem
+// @Description: chart_tag 图表标签表
+type ChartTagItem struct {
+	ChartTagId      int       `orm:"column(chart_tag_id);pk"`
+	ChartTagName    string    `description:"标签名称"`
+	ChartTagNameEn  string    `description:"标签名称(英文)"`
+	SysUserId       int       `description:"创建人id"`
+	VarietyTotal    int       `description:"配置关联品种的数量"`
+	SysUserRealName string    `description:"创建人姓名"`
+	ModifyTime      time.Time `description:"修改时间"`
+	CreateTime      time.Time `description:"创建时间"`
+}
+
+// GetTagItemList
+// @Description: 获取所有标签列表(列表页用到的)
+// @author: Roc
+// @datetime 2023-11-22 10:44:35
+// @return items []*ChartTag
+// @return err error
+func GetTagItemList() (items []*ChartTagItem, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT * FROM chart_tag WHERE 1 = 1 `
+	_, err = o.Raw(sql).QueryRows(&items)
+
+	return
+}

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

@@ -0,0 +1,239 @@
+package cross_variety
+
+import (
+	"eta/eta_mobile/models/data_manage/cross_variety/request"
+	"eta/eta_mobile/utils"
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
+	"strings"
+	"time"
+)
+
+// ChartTagVariety
+// @Description: chart_tag_variety 图表标签品种关系表
+type ChartTagVariety struct {
+	Id                        int       `orm:"column(id);pk"`
+	ChartTagId                int       `description:"标签id"`
+	ChartVarietyId            int       `description:"品种id"`
+	EdbInfoId                 int       `description:"指标id"`
+	LastUpdateSysUserId       int       `description:"最后一次操作人"`
+	LastUpdateSysUserRealName string    `description:"最后一次操作人真实姓名"`
+	ModifyTime                time.Time `description:"修改时间"`
+	CreateTime                time.Time `description:"创建时间"`
+}
+
+// GetChartTagVarietyByTagAndVariety
+// @Description: 根据标签id和品种id获取关系
+// @author: Roc
+// @datetime 2023-11-22 10:42:50
+// @param chartTagId int
+// @param chartVarietyId int
+// @return item *ChartTagVariety
+// @return err error
+func GetChartTagVarietyByTagAndVariety(chartTagId, chartVarietyId int) (item *ChartTagVariety, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT * FROM chart_tag_variety WHERE chart_tag_id = ? AND chart_variety_id = ?`
+	err = o.Raw(sql, chartTagId, chartVarietyId).QueryRow(&item)
+
+	return
+}
+
+// GetChartTagVarietyListByTag
+// @Description: 根据标签id获取所有绑定的品种列表
+// @author: Roc
+// @datetime 2023-11-22 10:44:35
+// @param chartTagId int
+// @param chartVarietyId int
+// @return items []*ChartTagVariety
+// @return err error
+func GetChartTagVarietyListByTag(chartTagId int) (items []*ChartTagVariety, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT * FROM chart_tag_variety WHERE chart_tag_id = ? `
+	_, err = o.Raw(sql, chartTagId).QueryRows(&items)
+
+	return
+}
+
+// GetChartTagVarietyListByTagAndVariety
+// @Description: 根据标签id和品种id列表获取所绑定的品种列表
+// @author: Roc
+// @datetime 2023-11-23 15:04:20
+// @param chartTagId int
+// @param varietyIdList []int
+// @return items []*ChartTagVariety
+// @return err error
+func GetChartTagVarietyListByTagAndVariety(chartTagId int, varietyIdList []int) (items []*ChartTagVariety, err error) {
+	num := len(varietyIdList)
+	if num <= 0 {
+		return
+	}
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT * FROM chart_tag_variety WHERE chart_tag_id = ? AND chart_variety_id in (` + utils.GetOrmInReplace(num) + `) `
+	_, err = o.Raw(sql, chartTagId, varietyIdList).QueryRows(&items)
+
+	return
+}
+
+// ChartTagVarietyItem
+// @Description: 图表标签/品种/指标数据
+type ChartTagVarietyItem struct {
+	Id             int     `orm:"column(id);pk"`
+	ChartTagId     int     `description:"标签id"`
+	ChartVarietyId int     `description:"品种id"`
+	EdbInfoId      int     `description:"指标id"`
+	EdbCode        string  `description:"指标编码"`
+	EdbName        string  `description:"指标名称"`
+	EndDate        string  `description:"数据的最晚日期"`
+	EndValue       float64 `description:"数据最新值"`
+}
+
+// GetChartTagVarietyItemListByTag
+// @Description: 根据标签id获取所有绑定的品种列表
+// @author: Roc
+// @datetime 2023-11-22 10:44:35
+// @param chartTagId int
+// @param chartVarietyId int
+// @return items []*ChartTagVariety
+// @return err error
+func GetChartTagVarietyItemListByTag(chartTagId int) (items []*ChartTagVarietyItem, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT a.*,b.edb_code,b.edb_name,b.end_date,b.end_value FROM chart_tag_variety a 
+         join edb_info b on a.edb_info_id=b.edb_info_id WHERE chart_tag_id = ? `
+	_, err = o.Raw(sql, chartTagId).QueryRows(&items)
+
+	return
+}
+
+// ChartTagVarietyCount
+// @Description: 签绑定的品种数量
+type ChartTagVarietyCount struct {
+	ChartTagId int `description:"标签id"`
+	Total      int `description:"标签配置的品种数量"`
+}
+
+// GetCountChartTagVarietyItemListByTag
+// @Description: 获取所有标签绑定的品种数量
+// @author: Roc
+// @datetime 2023-11-22 10:44:35
+// @return items []*ChartTagVarietyCount
+// @return err error
+func GetCountChartTagVarietyItemListByTag() (items []*ChartTagVarietyCount, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT chart_tag_id,count(1) total FROM chart_tag_variety a 
+         join edb_info b on a.edb_info_id=b.edb_info_id  group by chart_tag_id`
+	_, err = o.Raw(sql).QueryRows(&items)
+
+	return
+}
+
+// SaveVarietyEdb
+// @Description: 配置标签中的指标与品种的映射关系
+// @author: Roc
+// @datetime 2023-11-22 14:26:24
+// @param chartTagId int
+// @param list []request.VarietyEdbReq
+// @param sysUserId int
+// @param sysUserName string
+// @return err error
+func SaveVarietyEdb(chartTagId int, list []request.VarietyEdbReq, sysUserId int, sysUserName string) (err error) {
+	o, err := orm.NewOrmUsingDB("data").Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = o.Rollback()
+		} else {
+			_ = o.Commit()
+		}
+	}()
+
+	// 查找现在已经存在的品种和指标的关系
+	var items []*ChartTagVariety
+	sql := `SELECT * FROM chart_tag_variety WHERE chart_tag_id = ? `
+	_, err = o.Raw(sql, chartTagId).QueryRows(&items)
+	if err != nil {
+		return
+	}
+
+	hasMap := make(map[int]*ChartTagVariety)
+	existMap := make(map[int]*ChartTagVariety)
+	for _, v := range items {
+		hasMap[v.ChartVarietyId] = v
+		existMap[v.ChartVarietyId] = v
+	}
+
+	// 待添加的配置
+	addList := make([]*ChartTagVariety, 0)
+	for _, v := range list {
+		tmpChartTagVariety, ok := hasMap[v.ChartVarietyId]
+
+		// 找不到就插入
+		if !ok {
+			addList = append(addList, &ChartTagVariety{
+				Id:                        0,
+				ChartTagId:                chartTagId,
+				ChartVarietyId:            v.ChartVarietyId,
+				EdbInfoId:                 v.EdbInfoId,
+				LastUpdateSysUserId:       sysUserId,
+				LastUpdateSysUserRealName: sysUserName,
+				ModifyTime:                time.Now(),
+				CreateTime:                time.Now(),
+			})
+			continue
+		}
+
+		delete(existMap, v.ChartVarietyId)
+
+		// 找到了,如果指标不一致那就修改
+		if tmpChartTagVariety.EdbInfoId != v.EdbInfoId {
+			tmpChartTagVariety.EdbInfoId = v.EdbInfoId
+			tmpChartTagVariety.LastUpdateSysUserId = sysUserId
+			tmpChartTagVariety.LastUpdateSysUserRealName = sysUserName
+			tmpChartTagVariety.ModifyTime = time.Now()
+			_, err = o.Update(tmpChartTagVariety, "EdbInfoId", "LastUpdateSysUserId", "LastUpdateSysUserRealName", "ModifyTime")
+			if err != nil {
+				return
+			}
+		}
+	}
+
+	// 删除不要了的
+	if len(existMap) > 0 {
+		idStrList := make([]string, 0)
+		for id, _ := range existMap {
+			idStrList = append(idStrList, fmt.Sprint(id))
+		}
+		removeIdStr := strings.Join(idStrList, `,`)
+		sql = fmt.Sprintf(` DELETE FROM chart_tag_variety WHERE id in (%s) `, removeIdStr)
+		_, err = o.Raw(sql).Exec()
+		if err != nil {
+			return
+		}
+	}
+
+	// 添加配置
+	if len(addList) > 0 {
+		_, err = o.InsertMulti(len(addList), addList)
+		if err != nil {
+			return
+		}
+	}
+	return
+}
+
+// GetCountByEdbInfoId
+// @Description: 根据指标id获取其关联的品种数量
+// @author: Roc
+// @datetime 2023-11-28 19:43:42
+// @param edbInfoId int
+// @return total int
+// @return err error
+func GetCountByEdbInfoId(edbInfoId int) (total int, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT count(1) total FROM chart_tag_variety a 
+         join edb_info b on a.edb_info_id=b.edb_info_id WHERE edb_info_id = ?`
+	err = o.Raw(sql, edbInfoId).QueryRow(&total)
+
+	return
+}

+ 121 - 0
models/data_manage/cross_variety/chart_variety.go

@@ -0,0 +1,121 @@
+package cross_variety
+
+import (
+	"eta/eta_mobile/utils"
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+// ChartVariety
+// @Description: chart_variety 图表品种表
+type ChartVariety struct {
+	ChartVarietyId     int       `orm:"column(chart_variety_id);pk"`
+	ChartVarietyName   string    `description:"品种名称"`
+	ChartVarietyNameEn string    `description:"品种名称(英文)"`
+	SysUserId          int       `description:"创建人id"`
+	SysUserRealName    string    `description:"创建人姓名"`
+	ModifyTime         time.Time `description:"修改时间"`
+	CreateTime         time.Time `description:"创建时间"`
+}
+
+// GetVarietyById
+// @Description: 根据品种id获取品种详情
+// @author: Roc
+// @datetime 2023-11-21 14:55:31
+// @param id int
+// @return item *ChartVariety
+// @return err error
+func GetVarietyById(id int) (item *ChartVariety, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT * FROM chart_variety WHERE chart_variety_id = ?`
+	err = o.Raw(sql, id).QueryRow(&item)
+
+	return
+}
+
+// GetVarietyByName
+// @Description: 根据品种名称获取品种详情
+// @author: Roc
+// @datetime 2023-11-21 14:55:20
+// @param name string
+// @return item *ChartVariety
+// @return err error
+func GetVarietyByName(name string) (item *ChartVariety, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT * FROM chart_variety WHERE chart_variety_name = ?`
+	err = o.Raw(sql, name).QueryRow(&item)
+
+	return
+}
+
+// AddVariety
+// @Description: 添加品种
+// @author: Roc
+// @datetime 2023-11-21 14:52:56
+// @param item *ChartVariety
+// @return err error
+func AddVariety(item *ChartVariety) (err error) {
+	o := orm.NewOrmUsingDB("data")
+	lastId, err := o.Insert(item)
+	if err != nil {
+		return
+	}
+
+	item.ChartVarietyId = int(lastId)
+
+	return
+}
+
+// Update
+// @Description: 更新品种
+// @author: Roc
+// @receiver item
+// @datetime 2023-11-21 15:15:17
+// @param updateColList []string
+// @return err error
+func (item *ChartVariety) Update(updateColList []string) (err error) {
+	to := orm.NewOrmUsingDB("data")
+	_, err = to.Update(item, updateColList...)
+
+	return
+}
+
+// Delete 删除
+func (item *ChartVariety) Delete() (err error) {
+	o := orm.NewOrmUsingDB("data")
+	_, err = o.Delete(item)
+	return
+}
+
+// GetVarietyList
+// @Description: 获取所有品种列表
+// @author: Roc
+// @datetime 2023-11-22 10:44:35
+// @return items []*ChartVariety
+// @return err error
+func GetVarietyList() (items []*ChartVariety, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT * FROM chart_variety WHERE 1 = 1 `
+	_, err = o.Raw(sql).QueryRows(&items)
+
+	return
+}
+
+// GetVarietyListByIdList
+// @Description: 根据ID列表获取品种列表
+// @author: Roc
+// @datetime 2023-11-23 17:56:39
+// @param idList []int
+// @return items []*ChartVariety
+// @return err error
+func GetVarietyListByIdList(idList []int) (items []*ChartVariety, err error) {
+	num := len(idList)
+	if num <= 0 {
+		return
+	}
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT * FROM chart_variety WHERE 1 = 1 AND chart_variety_id in (` + utils.GetOrmInReplace(num) + `)`
+	_, err = o.Raw(sql, idList).QueryRows(&items)
+
+	return
+}

+ 47 - 0
models/data_manage/cross_variety/chart_variety_mapping.go

@@ -0,0 +1,47 @@
+package cross_variety
+
+import (
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+// ChartVarietyMapping
+// @Description: 图表与品种的关系表
+type ChartVarietyMapping struct {
+	Id             int       `orm:"column(id);pk"`
+	ChartInfoId    int       `description:"图表id"`
+	ChartVarietyId int       `description:"品种id"`
+	ModifyTime     time.Time `description:"修改时间"`
+	CreateTime     time.Time `description:"创建时间"`
+}
+
+// GetChartVarietyMappingList
+// @Description: 获取图表与品种的关系列表表
+// @author: Roc
+// @datetime 2023-11-24 15:22:36
+// @param chartInfoId int
+// @return items []*ChartVarietyMapping
+// @return err error
+func GetChartVarietyMappingList(chartInfoId int) (items []*ChartVarietyMapping, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT * FROM chart_variety_mapping WHERE chart_info_id = ? `
+	_, err = o.Raw(sql, chartInfoId).QueryRows(&items)
+	return
+}
+
+// GetCountChartByVarietyId
+// @Description: 根据品种id获取引用该标签的图表数量
+// @author: Roc
+// @datetime 2023-11-27 10:41:46
+// @param tagId int
+// @return total int64
+// @return err error
+func GetCountChartByVarietyId(varietyId int) (total int64, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT count(1) total FROM chart_info AS a JOIN
+    chart_variety_mapping AS b on a.chart_info_id = b.chart_info_id 
+    WHERE b.chart_variety_id = ? `
+	err = o.Raw(sql, varietyId).QueryRow(&total)
+
+	return
+}

+ 80 - 0
models/data_manage/cross_variety/request/chart.go

@@ -0,0 +1,80 @@
+package request
+
+// ChartConfigReq
+// @Description: 跨品种分析的图表配置
+type ChartConfigReq struct {
+	TagX           int               `description:"X轴的标签ID"`
+	TagY           int               `description:"Y轴的标签ID"`
+	CalculateValue int               `description:"计算窗口"`
+	CalculateUnit  string            `description:"计算频度"`
+	DateConfigList []ChartConfigDate `description:"日期配置列表"`
+	VarietyList    []int             `description:"品种id列表"`
+}
+
+// ChartConfigDate
+// @Description: 跨品种分析的日期配置
+type ChartConfigDate struct {
+	DateType int `description:"日期类型,,1:最新日期;2:N天前"`
+	Num      int
+}
+
+// AddChartReq
+// @Description: 添加图表的请求
+type AddChartReq struct {
+	ChartName      string            `description:"图表名称"`
+	LeftMin        string            `description:"图表左侧最小值"`
+	LeftMax        string            `description:"图表左侧最大值"`
+	ChartImage     string            `description:"图表截图,复制的时候才用到" json:"-"`
+	TagX           int               `description:"X轴的标签ID"`
+	TagY           int               `description:"Y轴的标签ID"`
+	CalculateValue int               `description:"计算窗口"`
+	CalculateUnit  string            `description:"计算频度"`
+	DateConfigList []ChartConfigDate `description:"日期配置列表"`
+	VarietyList    []int
+}
+
+// EditChartReq
+// @Description: 编辑图表的请求
+type EditChartReq struct {
+	ChartInfoId    int               `description:"图表id"`
+	ChartName      string            `description:"图表名称"`
+	LeftMin        string            `description:"图表左侧最小值"`
+	LeftMax        string            `description:"图表左侧最大值"`
+	ChartImage     string            `description:"图表截图,复制的时候才用到" json:"-"`
+	TagX           int               `description:"X轴的标签ID"`
+	TagY           int               `description:"Y轴的标签ID"`
+	CalculateValue int               `description:"计算窗口"`
+	CalculateUnit  string            `description:"计算频度"`
+	DateConfigList []ChartConfigDate `description:"日期配置列表"`
+	VarietyList    []int
+}
+
+// CopyAddChartInfoReq
+// @Description: 复制并新增图表
+type CopyAddChartInfoReq struct {
+	ChartInfoId int    `description:"待复制的图表id"`
+	ChartName   string `description:"图表名称"`
+}
+
+// EditChartEnInfoReq
+// @Description: 编辑图表英文信息
+type EditChartEnInfoReq struct {
+	ChartInfoId int                `description:"图表ID"`
+	ChartNameEn string             `description:"英文图表名称"`
+	TagList     []TagNameEnReq     `description:"标签名称"`
+	VarietyList []VarietyNameEnReq `description:"标签名称"`
+}
+
+// TagNameEnReq
+// @Description: 标签英文名称修改
+type TagNameEnReq struct {
+	ChartTagId int    `json:"ChartTagId"`
+	TagNameEn  string `json:"TagNameEn"`
+}
+
+// VarietyNameEnReq
+// @Description: 品种英文名称修改
+type VarietyNameEnReq struct {
+	ChartVarietyId int    `json:"ChartVarietyId"`
+	VarietyNameEn  string `json:"VarietyNameEn"`
+}

+ 31 - 0
models/data_manage/cross_variety/request/tag.go

@@ -0,0 +1,31 @@
+package request
+
+// AddTagReq 添加标签请求
+type AddTagReq struct {
+	TagName string `description:"标签名称"`
+}
+
+// EditTagReq 编辑标签请求
+type EditTagReq struct {
+	ChartTagId int    `description:"标签id"`
+	TagName    string `description:"标签名称"`
+}
+
+// DelTagReq 删除标签请求
+type DelTagReq struct {
+	ChartTagId int `description:"标签id"`
+}
+
+// SaveTagVarietyEdbReq
+// @Description: 配置标签中的指标与品种的映射关系
+type SaveTagVarietyEdbReq struct {
+	ChartTagId int             `description:"标签id"`
+	VarietyEdb []VarietyEdbReq `description:"品种和指标的映射关系"`
+}
+
+// VarietyEdbReq
+// @Description: 品种和指标的映射关系
+type VarietyEdbReq struct {
+	ChartVarietyId int `description:"品种id"`
+	EdbInfoId      int `description:"指标id"`
+}

+ 17 - 0
models/data_manage/cross_variety/request/variety.go

@@ -0,0 +1,17 @@
+package request
+
+// AddVarietyReq 添加品种请求
+type AddVarietyReq struct {
+	VarietyName string `description:"品种名称"`
+}
+
+// EditVarietyReq 编辑品种请求
+type EditVarietyReq struct {
+	ChartVarietyId int    `description:"品种id"`
+	VarietyName    string `description:"品种名称"`
+}
+
+// DelVarietyReq 删除品种请求
+type DelVarietyReq struct {
+	ChartVarietyId int `description:"品种id"`
+}

+ 21 - 0
models/data_manage/cross_variety/response/chart.go

@@ -0,0 +1,21 @@
+package response
+
+import (
+	"eta/eta_mobile/models/data_manage"
+	"eta/eta_mobile/models/data_manage/cross_variety"
+)
+
+// ChartPreviewResp
+// @Description: 图表预览返回
+type ChartPreviewResp struct {
+	EdbInfoList []*data_manage.ChartEdbInfoMapping
+	DataResp    interface{} `description:"图表数据,根据图的类型而定的,没有确定的数据格式"`
+}
+
+// ChartRelationResp
+// @Description: 图表关联配置返回
+type ChartRelationResp struct {
+	ChartInfo   *data_manage.ChartInfoView
+	TagList     []*cross_variety.ChartTag
+	VarietyList []*cross_variety.ChartVariety
+}

+ 26 - 0
models/data_manage/cross_variety/response/tag.go

@@ -0,0 +1,26 @@
+package response
+
+import (
+	"eta/eta_mobile/models/data_manage/cross_variety"
+	"github.com/rdlucklib/rdluck_tools/paging"
+)
+
+// TagDeleteCheckResp 标签删除检测数据返回
+type TagDeleteCheckResp struct {
+	DeleteStatus int    `description:"检测状态:0:默认值,如果为0,继续走其他校验,1:该标签已关联图表,不允许删除!"`
+	TipsMsg      string `description:"提示信息"`
+}
+
+// TagListResp
+// @Description: 标签列表数据
+type TagListResp struct {
+	List   []*cross_variety.ChartTagItem `description:"列表数据"`
+	Paging *paging.PagingItem
+}
+
+// VarietyEdbListResp
+// @Description: 品种与关系的数据返回
+type VarietyEdbListResp struct {
+	List   []*cross_variety.ChartTagVarietyItem `description:"列表数据"`
+	Paging *paging.PagingItem
+}

+ 19 - 0
models/data_manage/cross_variety/response/variety.go

@@ -0,0 +1,19 @@
+package response
+
+import (
+	"eta/eta_mobile/models/data_manage/cross_variety"
+	"github.com/rdlucklib/rdluck_tools/paging"
+)
+
+// VarietyDeleteCheckResp 品种删除检测数据返回
+type VarietyDeleteCheckResp struct {
+	DeleteStatus int    `description:"检测状态:0:默认值,如果为0,继续走其他校验,1:已关联图表的品种,不允许删除!"`
+	TipsMsg      string `description:"提示信息"`
+}
+
+// VarietyListResp
+// @Description: 品种列表数据
+type VarietyListResp struct {
+	List   []*cross_variety.ChartVariety `description:"列表数据"`
+	Paging *paging.PagingItem
+}

+ 2 - 2
models/data_manage/edb_data_baiinfo.go

@@ -25,7 +25,7 @@ func GetEdbDataBaiinfoMaxAndMinDate(edbCode string) (min_date, max_date string,
 }
 
 // 全部刷新有色数据
-func RefreshAllEdbDataByBaiinfo(edbInfoId, source int, edbCode, startDate, endDate string) (err error) {
+func RefreshAllEdbDataByBaiinfo(edbInfoId, source, subSource int, edbCode, startDate, endDate string) (err error) {
 	o := orm.NewOrmUsingDB("data")
 	to, err := o.Begin()
 	if err != nil {
@@ -46,7 +46,7 @@ func RefreshAllEdbDataByBaiinfo(edbInfoId, source int, edbCode, startDate, endDa
 
 	//获取已存在指标所有数据
 	existDataList := make([]*EdbDataBase, 0)
-	dataTableName := GetEdbDataTableName(source)
+	dataTableName := GetEdbDataTableName(source, subSource)
 	sql := `SELECT * FROM %s WHERE edb_info_id=? `
 	sql = fmt.Sprintf(sql, dataTableName)
 	_, err = to.Raw(sql, edbInfoId).QueryRows(&existDataList)

+ 79 - 31
models/data_manage/edb_data_base.go

@@ -8,12 +8,21 @@ import (
 )
 
 // 指标数据->存储表
-func GetEdbDataTableName(source int) (tableName string) {
+func GetEdbDataTableName(source, subSource int) (tableName string) {
 	switch source {
 	case utils.DATA_SOURCE_THS:
 		tableName = "edb_data_ths"
+		if subSource == utils.DATA_SUB_SOURCE_DATE {
+			tableName = "edb_data_ths_ds"
+		} else {
+			tableName = "edb_data_ths"
+		}
 	case utils.DATA_SOURCE_WIND:
-		tableName = "edb_data_wind"
+		if subSource == utils.DATA_SUB_SOURCE_DATE {
+			tableName = "edb_data_wind_wsd"
+		} else {
+			tableName = "edb_data_wind"
+		}
 	case utils.DATA_SOURCE_PB, utils.DATA_SOURCE_PB_FINANCE: //彭博经济数据、彭博财务数据
 		tableName = "edb_data_pb"
 	case utils.DATA_SOURCE_CALCULATE:
@@ -165,31 +174,6 @@ func GetEdbDataTableName(source int) (tableName string) {
 	return
 }
 
-//计算指标->关联的基础指标表
-//func GetEdbInfoCalculateTableName(source int) (tableName string) {
-//	switch source {
-//	case utils.DATA_SOURCE_CALCULATE:
-//		tableName = "edb_info_calculate"
-//	case utils.DATA_SOURCE_CALCULATE_LJZZY:
-//		tableName = "edb_info_calculate_ljzzy"
-//	case utils.DATA_SOURCE_CALCULATE_TBZ:
-//		tableName = "edb_info_calculate_tbz"
-//	case utils.DATA_SOURCE_CALCULATE_TCZ:
-//		tableName = "edb_info_calculate_tcz"
-//	case utils.DATA_SOURCE_CALCULATE_NSZYDPJJS:
-//		tableName = "edb_info_calculate_nszydpjjs"
-//	case utils.DATA_SOURCE_CALCULATE_HBZ:
-//		tableName = "edb_info_calculate_hbz"
-//	case utils.DATA_SOURCE_CALCULATE_HCZ:
-//		tableName = "edb_info_calculate_hcz"
-//	case utils.DATA_SOURCE_CALCULATE_BP:
-//		tableName = "edb_info_calculate_bp"
-//	default:
-//		tableName = ""
-//	}
-//	return
-//}
-
 type EdbDataBase struct {
 	EdbDataId     int `orm:"column(edb_data_id);pk"`
 	EdbInfoId     int
@@ -202,12 +186,12 @@ type EdbDataBase struct {
 	DataTimestamp int64
 }
 
-func GetEdbDataAllByEdbCode(edbCode string, source, limit int) (items []*EdbInfoSearchData, err error) {
+func GetEdbDataAllByEdbCode(edbCode string, source, subSource, limit int) (items []*EdbInfoSearchData, err error) {
 	var pars []interface{}
 	pars = append(pars, edbCode)
 	o := orm.NewOrmUsingDB("data")
 
-	tableName := GetEdbDataTableName(source)
+	tableName := GetEdbDataTableName(source, subSource)
 	sql := ` SELECT * FROM %s WHERE edb_code=? ORDER BY data_time DESC`
 	if limit > 0 {
 		sql += `  LIMIT ?  `
@@ -218,11 +202,75 @@ func GetEdbDataAllByEdbCode(edbCode string, source, limit int) (items []*EdbInfo
 	return
 }
 
-func GetEdbDataBaseByCodeAndDate(source int, edbCode string, startDate string) (count int, err error) {
+func GetEdbDataBaseByCodeAndDate(source, subSource int, edbCode string, startDate string) (count int, err error) {
 	o := orm.NewOrmUsingDB("data")
-	tableName := GetEdbDataTableName(source)
+	tableName := GetEdbDataTableName(source, subSource)
 	sql := ` SELECT COUNT(1) AS count FROM %s WHERE edb_code=? AND data_time=? `
 	sql = fmt.Sprintf(sql, tableName)
 	err = o.Raw(sql, edbCode, startDate).QueryRow(&count)
 	return
 }
+
+func GetEdbDataAllByEdbCodeAndSubSource(edbCode string, source, subSource, limit int) (items []*EdbInfoSearchData, err error) {
+	var pars []interface{}
+	pars = append(pars, edbCode)
+	o := orm.NewOrmUsingDB("data")
+
+	tableName := GetEdbDataTableNameAndSubSource(source, subSource)
+	sql := ` SELECT * FROM %s WHERE edb_code=? ORDER BY data_time DESC`
+	if limit > 0 {
+		sql += `  LIMIT ?  `
+		pars = append(pars, limit)
+	}
+	sql = fmt.Sprintf(sql, tableName)
+	_, err = o.Raw(sql, pars).QueryRows(&items)
+	return
+}
+
+// GetEdbDataTableName 指标数据->存储表
+func GetEdbDataTableNameAndSubSource(source, subSource int) (tableName string) {
+	switch source {
+	case utils.DATA_SOURCE_WIND:
+		if subSource == utils.DATA_SUB_SOURCE_EDB {
+			tableName = "edb_data_wind"
+		} else {
+			tableName = "edb_data_wind_wsd"
+		}
+	case utils.DATA_SOURCE_THS:
+		if subSource == utils.DATA_SUB_SOURCE_EDB {
+			tableName = "edb_data_ths"
+		} else {
+			tableName = "edb_data_ths_ds"
+		}
+	default:
+		edbSource := EdbSourceIdMap[source]
+		if edbSource != nil {
+			tableName = edbSource.TableName
+		}
+	}
+	return
+}
+
+func GetBaseIndexTableName(source int) (tableName string) {
+	edbSource := EdbSourceIdMap[source]
+	if edbSource != nil {
+		tableName = edbSource.IndexTableName
+	}
+	return
+}
+func GetBaseIndexInfoByEdbCode(edbCode string, source int) (item *BaseIndexInfo, err error) {
+	var pars []interface{}
+	pars = append(pars, edbCode)
+	o := orm.NewOrmUsingDB("data")
+
+	tableName := GetBaseIndexTableName(source)
+	if tableName == "" {
+		err = fmt.Errorf("未找到对应的表")
+		return
+	}
+	sql := ` SELECT * FROM %s WHERE index_code=? `
+
+	sql = fmt.Sprintf(sql, tableName)
+	err = o.Raw(sql, pars).QueryRow(&item)
+	return
+}

+ 3 - 3
models/data_manage/edb_data_calculate.go

@@ -50,7 +50,7 @@ func GetEdbDataCalculateByCodeAndDate(edbCode string, startDate string) (count i
 }
 
 // 刷新全部数据
-func RefreshAllCalculate(edbInfoIdArr []*EdbInfo, edbInfoId, source int, edbCode, formulaStr, startDate, endDate string, edbInfoIdBytes []string) (err error) {
+func RefreshAllCalculate(edbInfoIdArr []*EdbInfo, edbInfoId, source, subSource int, edbCode, formulaStr, startDate, endDate string, edbInfoIdBytes []string) (err error) {
 	o := orm.NewOrmUsingDB("data")
 	to, err := o.Begin()
 	if err != nil {
@@ -79,7 +79,7 @@ func RefreshAllCalculate(edbInfoIdArr []*EdbInfo, edbInfoId, source int, edbCode
 			pars = append(pars, endDate)
 		}
 		fmt.Println("v.Source:", v.Source)
-		dataList, err := GetEdbDataListAll(condition, pars, v.Source, 1)
+		dataList, err := GetEdbDataListAll(condition, pars, v.Source, v.SubSource, 1)
 		if err != nil {
 			return err
 		}
@@ -106,7 +106,7 @@ func RefreshAllCalculate(edbInfoIdArr []*EdbInfo, edbInfoId, source int, edbCode
 
 	//获取指标所有数据
 	dataList := make([]*EdbDataBase, 0)
-	dataTableName := GetEdbDataTableName(source)
+	dataTableName := GetEdbDataTableName(source, subSource)
 	sql := `SELECT * FROM %s WHERE edb_info_id=? `
 	sql = fmt.Sprintf(sql, dataTableName)
 	_, err = to.Raw(sql, edbInfoId).QueryRows(&dataList)

+ 1 - 1
models/data_manage/edb_data_calculate_time_shift.go

@@ -122,7 +122,7 @@ func EditCalculateTimeShift(req *EdbInfoCalculateBatchEditReq, fromEdbInfo *EdbI
 		condition += " AND edb_info_id=? "
 		pars = append(pars, req.FromEdbInfoId)
 		fmt.Println("EdbInfoId:", req.FromEdbInfoId)
-		dataList, err := GetEdbDataListAll(condition, pars, fromEdbInfo.Source, 0)
+		dataList, err := GetEdbDataListAll(condition, pars, fromEdbInfo.Source, fromEdbInfo.SubSource, 0)
 		if err != nil {
 			return edbInfoId, err
 		}

+ 3 - 3
models/data_manage/edb_data_cffex.go

@@ -123,7 +123,7 @@ func GetEdbDataByCffex(edbCode, suffix, startDate, endDate string) (searchItem *
 		_ = to.Commit()
 	}
 	size := utils.EDB_DATA_LIMIT
-	dataList, err = GetEdbDataAllByEdbCode(edbCode, utils.DATA_SOURCE_CFFEX, size)
+	dataList, err = GetEdbDataAllByEdbCode(edbCode, utils.DATA_SOURCE_CFFEX, utils.DATA_SUB_SOURCE_EDB, size)
 	if err != nil {
 		utils.FileLogData.Info("GetEdbDataCffexByCode Err:%s", err.Error())
 		return searchItem, err
@@ -246,7 +246,7 @@ func RefreshEdbDataByCffex(edbInfoId int, edbCode, startDate, endDate string) (e
 }
 
 // RefreshAllEdbDataByCffex 全部刷新中金所
-func RefreshAllEdbDataByCffex(edbInfoId, source int, edbCode, startDate, endDate string) (err error) {
+func RefreshAllEdbDataByCffex(edbInfoId, source, subSource int, edbCode, startDate, endDate string) (err error) {
 	o := orm.NewOrmUsingDB("data")
 	to, err := o.Begin()
 	if err != nil {
@@ -297,7 +297,7 @@ func RefreshAllEdbDataByCffex(edbInfoId, source int, edbCode, startDate, endDate
 
 	//获取指标所有数据
 	dataList := make([]*EdbDataBase, 0)
-	dataTableName := GetEdbDataTableName(source)
+	dataTableName := GetEdbDataTableName(source, subSource)
 	sql := `SELECT * FROM %s WHERE edb_info_id=? `
 	sql = fmt.Sprintf(sql, dataTableName)
 	_, err = to.Raw(sql, edbInfoId).QueryRows(&dataList)

+ 2 - 2
models/data_manage/edb_data_coal.go

@@ -156,7 +156,7 @@ func RefreshEdbDataByCoal(edbInfoId int, edbCode, startDate, endDate string) (er
 }
 
 // RefreshAllEdbDataByCoal 全部刷新中金所
-func RefreshAllEdbDataByCoal(edbInfoId, source int, edbCode, startDate, endDate string) (err error) {
+func RefreshAllEdbDataByCoal(edbInfoId, source, subSource int, edbCode, startDate, endDate string) (err error) {
 	o := orm.NewOrmUsingDB("data")
 	to, err := o.Begin()
 	if err != nil {
@@ -205,7 +205,7 @@ func RefreshAllEdbDataByCoal(edbInfoId, source int, edbCode, startDate, endDate
 
 	//获取指标所有数据
 	dataList := make([]*EdbDataBase, 0)
-	dataTableName := GetEdbDataTableName(source)
+	dataTableName := GetEdbDataTableName(source, subSource)
 	sql := `SELECT * FROM %s WHERE edb_info_id=? `
 	sql = fmt.Sprintf(sql, dataTableName)
 	_, err = to.Raw(sql, edbInfoId).QueryRows(&dataList)

+ 3 - 3
models/data_manage/edb_data_dl.go

@@ -124,7 +124,7 @@ func GetEdbDataByDl(edbCode, suffix, startDate, endDate string) (searchItem *Edb
 	}
 
 	size := utils.EDB_DATA_LIMIT
-	dataList, err = GetEdbDataAllByEdbCode(edbCode, utils.DATA_SOURCE_DL, size)
+	dataList, err = GetEdbDataAllByEdbCode(edbCode, utils.DATA_SOURCE_DL, utils.DATA_SUB_SOURCE_EDB, size)
 	if err != nil {
 		utils.FileLogData.Info("GetEdbDataDlByCode Err:%s", err.Error())
 		return searchItem, err
@@ -247,7 +247,7 @@ func RefreshEdbDataByDl(edbInfoId int, edbCode, startDate, endDate string) (err
 }
 
 // RefreshAllEdbDataByDl 全部刷新大商所
-func RefreshAllEdbDataByDl(edbInfoId, source int, edbCode, startDate, endDate string) (err error) {
+func RefreshAllEdbDataByDl(edbInfoId, source, subSource int, edbCode, startDate, endDate string) (err error) {
 	o := orm.NewOrmUsingDB("data")
 	to, err := o.Begin()
 	if err != nil {
@@ -298,7 +298,7 @@ func RefreshAllEdbDataByDl(edbInfoId, source int, edbCode, startDate, endDate st
 
 	//获取指标所有数据
 	dataList := make([]*EdbDataBase, 0)
-	dataTableName := GetEdbDataTableName(source)
+	dataTableName := GetEdbDataTableName(source, subSource)
 	sql := `SELECT * FROM %s WHERE edb_info_id=? `
 	sql = fmt.Sprintf(sql, dataTableName)
 	_, err = to.Raw(sql, edbInfoId).QueryRows(&dataList)

+ 2 - 2
models/data_manage/edb_data_gie.go

@@ -251,7 +251,7 @@ func RefreshEdbDataByGie(edbInfoId int, edbCode, startDate, endDate string) (err
 }
 
 // RefreshAllEdbDataByGie 全部刷新欧洲天然气
-func RefreshAllEdbDataByGie(edbInfoId, source int, edbCode, startDate, endDate string) (err error) {
+func RefreshAllEdbDataByGie(edbInfoId, source, subSource int, edbCode, startDate, endDate string) (err error) {
 	o := orm.NewOrmUsingDB("data")
 	to, err := o.Begin()
 	if err != nil {
@@ -316,7 +316,7 @@ func RefreshAllEdbDataByGie(edbInfoId, source int, edbCode, startDate, endDate s
 	fmt.Println("all eicDataList", len(eicDataList))
 	//获取指标所有数据
 	dataList := make([]*EdbDataBase, 0)
-	dataTableName := GetEdbDataTableName(source)
+	dataTableName := GetEdbDataTableName(source, subSource)
 	sql := `SELECT * FROM %s WHERE edb_info_id=? `
 	sql = fmt.Sprintf(sql, dataTableName)
 	_, err = to.Raw(sql, edbInfoId).QueryRows(&dataList)

+ 1 - 1
models/data_manage/edb_data_insert_config.go

@@ -30,7 +30,7 @@ func GetEdbDataInsertConfigByEdbId(edbInfoId int) (item *EdbDataInsertConfig, er
 func CreateEdbDataInsertConfigAndData(edbInfo *EdbInfo, date time.Time, value float64) (err error, errMsg string, isSendEmail bool) {
 	isSendEmail = true
 
-	tableName := GetEdbDataTableName(edbInfo.Source)
+	tableName := GetEdbDataTableName(edbInfo.Source, edbInfo.SubSource)
 	if tableName == `` {
 		err = errors.New("找不到该指标的数据表")
 		return

+ 2 - 2
models/data_manage/edb_data_lz.go

@@ -234,7 +234,7 @@ func RefreshEdbDataByLz(edbInfoId int, edbCode, startDate, endDate string) (err
 }
 
 // 全部刷新隆众数据
-func RefreshAllEdbDataByLz(edbInfoId, source int, edbCode, startDate, endDate string) (err error) {
+func RefreshAllEdbDataByLz(edbInfoId, source, subSource int, edbCode, startDate, endDate string) (err error) {
 	o := orm.NewOrmUsingDB("data")
 	to, err := o.Begin()
 	if err != nil {
@@ -275,7 +275,7 @@ func RefreshAllEdbDataByLz(edbInfoId, source int, edbCode, startDate, endDate st
 
 	//获取指标所有数据
 	dataList := make([]*EdbDataBase, 0)
-	dataTableName := GetEdbDataTableName(source)
+	dataTableName := GetEdbDataTableName(source, subSource)
 	sql := `SELECT * FROM %s WHERE edb_info_id=? `
 	sql = fmt.Sprintf(sql, dataTableName)
 	_, err = to.Raw(sql, edbInfoId).QueryRows(&dataList)

+ 5 - 5
models/data_manage/edb_data_manual.go

@@ -221,7 +221,7 @@ func RefreshEdbDataByManual(edbInfoId int, edbCode, startDate, endDate string) (
 }
 
 // 刷新手工指标数据
-func RefreshAllEdbDataByManual(edbInfoId, source int, edbCode string) (err error) {
+func RefreshAllEdbDataByManual(edbInfoId, source, subSource int, edbCode string) (err error) {
 	o := orm.NewOrmUsingDB("data")
 	to, err := o.Begin()
 	if err != nil {
@@ -251,7 +251,7 @@ func RefreshAllEdbDataByManual(edbInfoId, source int, edbCode string) (err error
 	manualDataList, err := GetEdbdataManualByTradeCode(condition, pars)
 	//获取指标所有数据
 	existDataList := make([]*EdbDataBase, 0)
-	dataTableName := GetEdbDataTableName(source)
+	dataTableName := GetEdbDataTableName(source, subSource)
 	sql := `SELECT * FROM %s WHERE edb_info_id=? `
 	sql = fmt.Sprintf(sql, dataTableName)
 	_, err = to.Raw(sql, edbInfoId).QueryRows(&existDataList)
@@ -297,7 +297,7 @@ func RefreshAllEdbDataByManual(edbInfoId, source int, edbCode string) (err error
 	}
 	for _, v := range existDataList {
 		if _, ok := manualMap[v.DataTime]; !ok {
-			go DeleteEdbDataByIdAndSource(v.EdbDataId, utils.DATA_SOURCE_MANUAL)
+			go DeleteEdbDataByIdAndSource(v.EdbDataId, utils.DATA_SOURCE_MANUAL, utils.DATA_SUB_SOURCE_EDB)
 		}
 	}
 	fmt.Println("isAdd:", isAdd)
@@ -312,9 +312,9 @@ func RefreshAllEdbDataByManual(edbInfoId, source int, edbCode string) (err error
 	return
 }
 
-func DeleteEdbDataByIdAndSource(edbDataId, source int) (err error) {
+func DeleteEdbDataByIdAndSource(edbDataId, source, subSource int) (err error) {
 	sql := ` DELETE FROM %s WHERE edb_data_id=? `
-	tableName := GetEdbDataTableName(source)
+	tableName := GetEdbDataTableName(source, subSource)
 	sql = fmt.Sprintf(sql, tableName)
 
 	o := orm.NewOrmUsingDB("data")

+ 2 - 2
models/data_manage/edb_data_sci.go

@@ -25,7 +25,7 @@ func GetEdbDataSciMaxAndMinDate(edbCode string) (min_date, max_date string, err
 }
 
 // 全部刷新有色数据
-func RefreshAllEdbDataBySci(edbInfoId, source int, edbCode, startDate, endDate string) (err error) {
+func RefreshAllEdbDataBySci(edbInfoId, source, subSource int, edbCode, startDate, endDate string) (err error) {
 	o := orm.NewOrmUsingDB("data")
 	to, err := o.Begin()
 	if err != nil {
@@ -46,7 +46,7 @@ func RefreshAllEdbDataBySci(edbInfoId, source int, edbCode, startDate, endDate s
 
 	//获取已存在指标所有数据
 	existDataList := make([]*EdbDataBase, 0)
-	dataTableName := GetEdbDataTableName(source)
+	dataTableName := GetEdbDataTableName(source, subSource)
 	sql := `SELECT * FROM %s WHERE edb_info_id=? `
 	sql = fmt.Sprintf(sql, dataTableName)
 	_, err = to.Raw(sql, edbInfoId).QueryRows(&existDataList)

+ 3 - 3
models/data_manage/edb_data_sh.go

@@ -124,7 +124,7 @@ func GetEdbDataBySh(edbCode, suffix, startDate, endDate string) (searchItem *Edb
 	}
 
 	size := utils.EDB_DATA_LIMIT
-	dataList, err = GetEdbDataAllByEdbCode(edbCode, utils.DATA_SOURCE_SH, size)
+	dataList, err = GetEdbDataAllByEdbCode(edbCode, utils.DATA_SOURCE_SH, utils.DATA_SUB_SOURCE_EDB, size)
 	if err != nil {
 		utils.FileLogData.Info("GetEdbDataShByCode Err:%s", err.Error())
 		return searchItem, err
@@ -244,7 +244,7 @@ func RefreshEdbDataBySh(edbInfoId int, edbCode, startDate, endDate string) (err
 }
 
 // RefreshAllEdbDataBySh 全部刷新上期所
-func RefreshAllEdbDataBySh(edbInfoId, source int, edbCode, startDate, endDate string) (err error) {
+func RefreshAllEdbDataBySh(edbInfoId, source, subSource int, edbCode, startDate, endDate string) (err error) {
 	o := orm.NewOrmUsingDB("data")
 	to, err := o.Begin()
 	if err != nil {
@@ -295,7 +295,7 @@ func RefreshAllEdbDataBySh(edbInfoId, source int, edbCode, startDate, endDate st
 
 	//获取指标所有数据
 	dataList := make([]*EdbDataBase, 0)
-	dataTableName := GetEdbDataTableName(source)
+	dataTableName := GetEdbDataTableName(source, subSource)
 	sql := `SELECT * FROM %s WHERE edb_info_id=? `
 	sql = fmt.Sprintf(sql, dataTableName)
 	_, err = to.Raw(sql, edbInfoId).QueryRows(&dataList)

+ 3 - 3
models/data_manage/edb_data_shfe.go

@@ -123,7 +123,7 @@ func GetEdbDataByShfe(edbCode, suffix, startDate, endDate string) (searchItem *E
 		_ = to.Commit()
 	}
 	size := utils.EDB_DATA_LIMIT
-	dataList, err = GetEdbDataAllByEdbCode(edbCode, utils.DATA_SOURCE_SHFE, size)
+	dataList, err = GetEdbDataAllByEdbCode(edbCode, utils.DATA_SOURCE_SHFE, utils.DATA_SUB_SOURCE_EDB, size)
 	if err != nil {
 		utils.FileLogData.Info("GetEdbDataShfeByCode Err:%s", err.Error())
 		return searchItem, err
@@ -246,7 +246,7 @@ func RefreshEdbDataByShfe(edbInfoId int, edbCode, startDate, endDate string) (er
 }
 
 // RefreshAllEdbDataByShfe 全部刷新上期能源
-func RefreshAllEdbDataByShfe(edbInfoId, source int, edbCode, startDate, endDate string) (err error) {
+func RefreshAllEdbDataByShfe(edbInfoId, source, subSource int, edbCode, startDate, endDate string) (err error) {
 	o := orm.NewOrmUsingDB("data")
 	to, err := o.Begin()
 	if err != nil {
@@ -300,7 +300,7 @@ func RefreshAllEdbDataByShfe(edbInfoId, source int, edbCode, startDate, endDate
 
 	//获取指标所有数据
 	dataList := make([]*EdbDataBase, 0)
-	dataTableName := GetEdbDataTableName(source)
+	dataTableName := GetEdbDataTableName(source, subSource)
 	sql := `SELECT * FROM %s WHERE edb_info_id=? `
 	sql = fmt.Sprintf(sql, dataTableName)
 	_, err = to.Raw(sql, edbInfoId).QueryRows(&dataList)

+ 63 - 0
models/data_manage/edb_data_ths_ds.go

@@ -0,0 +1,63 @@
+package data_manage
+
+import (
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
+)
+
+func ModifyEdbInfoThsDsDataStatus(edbInfoId int64, edbCode string) (err error) {
+	o := orm.NewOrmUsingDB("data")
+	tableName := `edb_data_ths_ds`
+	sql := ` UPDATE %s SET edb_info_id=?,modify_time=NOW() WHERE edb_code=? `
+	sql = fmt.Sprintf(sql, tableName)
+	_, err = o.Raw(sql, edbInfoId, edbCode).Exec()
+	return
+}
+
+// GetEdbDataList 获取指标的数据(日期正序返回)
+func GetEdbDataThsDsList(endInfoId int, startDate, endDate string) (list []*EdbDataList, err error) {
+	tableName := `edb_data_ths_ds`
+	var pars []interface{}
+	sql := `SELECT edb_data_id,edb_info_id,data_time,value,data_timestamp FROM %s WHERE edb_info_id=? `
+	if startDate != "" {
+		sql += ` AND data_time>=? `
+		pars = append(pars, startDate)
+	}
+	if endDate != "" {
+		sql += ` AND data_time<=? `
+		pars = append(pars, endDate)
+	}
+
+	sql += ` ORDER BY data_time ASC `
+	sql = fmt.Sprintf(sql, tableName)
+	o := orm.NewOrmUsingDB("data")
+	_, err = o.Raw(sql, endInfoId, pars).QueryRows(&list)
+	return
+}
+
+func GetTHsDsDataCountByCondition(condition string, pars []interface{}, source int) (count int, err error) {
+	o := orm.NewOrmUsingDB("data")
+	tableName := `edb_data_ths_ds`
+	sql := ` SELECT COUNT(1) AS count FROM %s WHERE 1=1 `
+	sql = fmt.Sprintf(sql, tableName)
+	if condition != "" {
+		sql += condition
+	}
+	err = o.Raw(sql, pars).QueryRow(&count)
+	return
+}
+
+func GetThsDsDataListByCondition(condition string, pars []interface{}, source, pageSize, startSize int) (item []*EdbData, err error) {
+	o := orm.NewOrmUsingDB("data")
+	tableName := `edb_data_ths_ds`
+	sql := ` SELECT * FROM %s WHERE 1=1 `
+	sql = fmt.Sprintf(sql, tableName)
+
+	if condition != "" {
+		sql += condition
+	}
+	sql += ` ORDER BY data_time DESC `
+	sql += ` LIMIT ?,? `
+	_, err = o.Raw(sql, pars, startSize, pageSize).QueryRows(&item)
+	return
+}

+ 63 - 0
models/data_manage/edb_data_wind_wsd.go

@@ -0,0 +1,63 @@
+package data_manage
+
+import (
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
+)
+
+func ModifyEdbInfoWindWsdDataStatus(source, subSource int, edbInfoId int64, edbCode string) (err error) {
+	o := orm.NewOrmUsingDB("data")
+	tableName := GetEdbDataTableNameAndSubSource(source, subSource)
+	sql := ` UPDATE %s SET edb_info_id=?,modify_time=NOW() WHERE edb_code=? `
+	sql = fmt.Sprintf(sql, tableName)
+	_, err = o.Raw(sql, edbInfoId, edbCode).Exec()
+	return
+}
+
+// GetEdbDataList 获取指标的数据(日期正序返回)
+func GetEdbDataWsdList(endInfoId int, startDate, endDate string) (list []*EdbDataList, err error) {
+	tableName := `edb_data_wind_wsd`
+	var pars []interface{}
+	sql := `SELECT edb_data_id,edb_info_id,data_time,value,data_timestamp FROM %s WHERE edb_info_id=? `
+	if startDate != "" {
+		sql += ` AND data_time>=? `
+		pars = append(pars, startDate)
+	}
+	if endDate != "" {
+		sql += ` AND data_time<=? `
+		pars = append(pars, endDate)
+	}
+
+	sql += ` ORDER BY data_time ASC `
+	sql = fmt.Sprintf(sql, tableName)
+	o := orm.NewOrmUsingDB("data")
+	_, err = o.Raw(sql, endInfoId, pars).QueryRows(&list)
+	return
+}
+
+func GetEdbWsdDataCountByCondition(condition string, pars []interface{}, source int) (count int, err error) {
+	o := orm.NewOrmUsingDB("data")
+	tableName := `edb_data_wind_wsd`
+	sql := ` SELECT COUNT(1) AS count FROM %s WHERE 1=1 `
+	sql = fmt.Sprintf(sql, tableName)
+	if condition != "" {
+		sql += condition
+	}
+	err = o.Raw(sql, pars).QueryRow(&count)
+	return
+}
+
+func GetEdbWsdDataListByCondition(condition string, pars []interface{}, source, pageSize, startSize int) (item []*EdbData, err error) {
+	o := orm.NewOrmUsingDB("data")
+	tableName := `edb_data_wind_wsd`
+	sql := ` SELECT * FROM %s WHERE 1=1 `
+	sql = fmt.Sprintf(sql, tableName)
+
+	if condition != "" {
+		sql += condition
+	}
+	sql += ` ORDER BY data_time DESC `
+	sql += ` LIMIT ?,? `
+	_, err = o.Raw(sql, pars, startSize, pageSize).QueryRows(&item)
+	return
+}

+ 0 - 350
models/data_manage/edb_data_zz.go

@@ -1,11 +1,8 @@
 package data_manage
 
 import (
-	"eta/eta_mobile/utils"
 	"fmt"
 	"github.com/beego/beego/v2/client/orm"
-	"strconv"
-	"strings"
 	"time"
 )
 
@@ -64,307 +61,6 @@ func GetEdbDataZzMaxOrMinDate(edbCode string) (minDate, maxDate string, err erro
 	return
 }
 
-func GetEdbDataByZz(edbCode, suffix, startDate, endDate string) (searchItem *EdbInfoSearch, err error) {
-	o := orm.NewOrmUsingDB("data")
-	to, err := o.Begin()
-	if err != nil {
-		return
-	}
-	searchItem = new(EdbInfoSearch)
-	searchItem.EdbCode = edbCode
-	zzBaseDataAll, err := GetBaseFromZhengzhouDataAllByIndexCode(edbCode, suffix)
-	if err != nil && err.Error() != utils.ErrNoRow() {
-		return
-	}
-
-	var isAdd bool
-	addSql := ` INSERT INTO edb_data_zz(edb_info_id,edb_code,data_time,value,create_time,modify_time,status,data_timestamp) values `
-	dataList := make([]*EdbInfoSearchData, 0)
-	existMap := make(map[string]string)
-
-	for _, sv := range zzBaseDataAll {
-		eDate := sv.DataTime
-		dataTime, err := time.Parse(utils.FormatDate, eDate)
-		if err != nil {
-			fmt.Println("time.Parse Err:" + eDate)
-			return nil, err
-		}
-		timestamp := dataTime.UnixNano() / 1e6
-		timeStr := fmt.Sprintf("%d", timestamp)
-		if _, ok := existMap[eDate]; !ok {
-			if suffix == "deal" {
-				addSql += GetAddSql("0", edbCode, eDate, timeStr, sv.DealValue)
-			} else if suffix == "buy" {
-				addSql += GetAddSql("0", edbCode, eDate, timeStr, sv.BuyValue)
-			} else {
-				addSql += GetAddSql("0", edbCode, eDate, timeStr, sv.SoldValue)
-			}
-			isAdd = true
-		}
-		if suffix == "deal" {
-			existMap[eDate] = sv.DealValue
-		} else if suffix == "buy" {
-			existMap[eDate] = sv.BuyValue
-		} else {
-			existMap[eDate] = sv.SoldValue
-		}
-	}
-	if isAdd {
-		addSql = strings.TrimRight(addSql, ",")
-		utils.FileLog.Info("addSql:" + addSql)
-		_, err = to.Raw(addSql).Exec()
-		if err != nil {
-			return searchItem, err
-		}
-	}
-	if err != nil {
-		_ = to.Rollback()
-	} else {
-		_ = to.Commit()
-	}
-	size := utils.EDB_DATA_LIMIT
-	dataList, err = GetEdbDataAllByEdbCode(edbCode, utils.DATA_SOURCE_ZZ, size)
-	if err != nil {
-		utils.FileLogData.Info("GetEdbDataZzByCode Err:%s", err.Error())
-		return searchItem, err
-	}
-	minDate, maxDate, err := GetEdbDataZzMaxOrMinDate(edbCode)
-	if err != nil {
-		return searchItem, err
-	}
-	searchItem.DataList = dataList
-	searchItem.StartDate = minDate
-	searchItem.EndDate = maxDate
-	if searchItem.DataList == nil {
-		searchItem.DataList = make([]*EdbInfoSearchData, 0)
-	}
-	return
-}
-
-// RefreshEdbDataByZz 刷新郑商所指标数据
-func RefreshEdbDataByZz(edbInfoId int, edbCode, startDate, endDate string) (err error) {
-	o := orm.NewOrmUsingDB("data")
-	to, err := o.Begin()
-	if err != nil {
-		return
-	}
-	defer func() {
-		if err != nil {
-			_ = to.Rollback()
-		} else {
-			_ = to.Commit()
-		}
-	}()
-	if err != nil {
-		return
-	}
-	var suffix string
-	if strings.Contains(edbCode, "deal") {
-		suffix = "deal"
-	} else if strings.Contains(edbCode, "buy") {
-		suffix = "buy"
-	} else if strings.Contains(edbCode, "sold") {
-		suffix = "sold"
-	}
-	edbInfoIdStr := strconv.Itoa(edbInfoId)
-	//计算数据
-	var condition string
-	var pars []interface{}
-
-	if edbCode != "" {
-		if suffix == "deal" {
-			condition += " AND deal_code=? "
-		} else if suffix == "buy" {
-			condition += " AND buy_code=? "
-		} else {
-			condition += " AND sold_code=? "
-		}
-		pars = append(pars, edbCode)
-	}
-
-	if startDate != "" {
-		condition += " AND data_time>=? "
-		pars = append(pars, startDate)
-	}
-
-	if endDate != "" {
-		condition += " AND data_time<=? "
-		pars = append(pars, endDate)
-	}
-
-	glDataList, err := GetZzDataByTradeCode(condition, pars)
-
-	addSql := ` INSERT INTO edb_data_zz(edb_info_id,edb_code,data_time,value,create_time,modify_time,status,data_timestamp) values `
-	var isAdd bool
-	existMap := make(map[string]string)
-	for _, v := range glDataList {
-		var value string
-		if suffix == "deal" {
-			value = v.DealValue
-		} else if suffix == "buy" {
-			value = v.BuyValue
-		} else {
-			value = v.SoldValue
-		}
-		item := v
-		itemValue := value
-		if _, ok := existMap[v.DataTime]; !ok {
-			count, err := GetEdbDataZzByCodeAndDate(edbCode, v.DataTime)
-			if err != nil && err.Error() != utils.ErrNoRow() {
-				return err
-			}
-			if count <= 0 {
-				eDate := item.DataTime
-				sValue := itemValue
-				if sValue != "" {
-					dataTime, err := time.Parse(utils.FormatDate, eDate)
-					if err != nil {
-						return err
-					}
-					timestamp := dataTime.UnixNano() / 1e6
-					timeStr := fmt.Sprintf("%d", timestamp)
-					addSql += GetAddSql(edbInfoIdStr, edbCode, eDate, timeStr, sValue)
-					isAdd = true
-				}
-			} else {
-				err = ModifyEdbDataZz(int64(edbInfoId), v.DataTime, value)
-				if err != nil {
-					return err
-				}
-			}
-		}
-		existMap[v.DataTime] = value
-	}
-	if isAdd {
-		addSql = strings.TrimRight(addSql, ",")
-		_, err = to.Raw(addSql).Exec()
-		if err != nil {
-			return err
-		}
-	}
-	return
-}
-
-// RefreshAllEdbDataByZz 全部刷新郑商所
-func RefreshAllEdbDataByZz(edbInfoId, source int, edbCode, startDate, endDate string) (err error) {
-	o := orm.NewOrmUsingDB("data")
-	to, err := o.Begin()
-	if err != nil {
-		return
-	}
-	defer func() {
-		if err != nil {
-			_ = to.Rollback()
-		} else {
-			_ = to.Commit()
-		}
-	}()
-	if err != nil {
-		return
-	}
-	var suffix string
-	if strings.Contains(edbCode, "deal") {
-		suffix = "deal"
-	} else if strings.Contains(edbCode, "buy") {
-		suffix = "buy"
-	} else if strings.Contains(edbCode, "sold") {
-		suffix = "sold"
-	}
-	edbInfoIdStr := strconv.Itoa(edbInfoId)
-	//计算数据
-	var condition string
-	var pars []interface{}
-
-	if edbCode != "" {
-		if suffix == "deal" {
-			condition += " AND deal_code=? "
-		} else if suffix == "buy" {
-			condition += " AND buy_code=? "
-		} else {
-			condition += " AND sold_code=? "
-		}
-		pars = append(pars, edbCode)
-	}
-
-	if startDate != "" {
-		condition += " AND data_time>=? "
-		pars = append(pars, startDate)
-	}
-
-	if endDate != "" {
-		condition += " AND data_time<=? "
-		pars = append(pars, endDate)
-	}
-
-	glDataList, err := GetZzDataByTradeCode(condition, pars)
-
-	//获取指标所有数据
-	dataList := make([]*EdbDataBase, 0)
-	dataTableName := GetEdbDataTableName(source)
-	sql := `SELECT * FROM %s WHERE edb_info_id=? `
-	sql = fmt.Sprintf(sql, dataTableName)
-	_, err = to.Raw(sql, edbInfoId).QueryRows(&dataList)
-	if err != nil {
-		return err
-	}
-	dataMap := make(map[string]string)
-	for _, v := range dataList {
-		dataMap[v.DataTime] = v.Value
-	}
-
-	addSql := ` INSERT INTO edb_data_zz(edb_info_id,edb_code,data_time,value,create_time,modify_time,status,data_timestamp) values `
-	var isAdd bool
-	existMap := make(map[string]string)
-	for _, v := range glDataList {
-		var value string
-		if suffix == "deal" {
-			value = v.DealValue
-		} else if suffix == "buy" {
-			value = v.BuyValue
-		} else {
-			value = v.SoldValue
-		}
-		item := v
-		itemValue := value
-		if _, ok := existMap[v.DataTime]; !ok {
-			eDate := item.DataTime
-			sValue := itemValue
-			if sValue != "" {
-				dataTime, err := time.Parse(utils.FormatDate, eDate)
-				if err != nil {
-					return err
-				}
-				timestamp := dataTime.UnixNano() / 1e6
-				timeStr := fmt.Sprintf("%d", timestamp)
-				saveValue := sValue
-
-				if existVal, ok := dataMap[eDate]; !ok {
-					addSql += GetAddSql(edbInfoIdStr, edbCode, eDate, timeStr, saveValue)
-					isAdd = true
-				} else {
-					if existVal != saveValue {
-						sql := ` UPDATE %s SET value=?,modify_time=NOW() WHERE edb_info_id=? AND data_time=? `
-						sql = fmt.Sprintf(sql, dataTableName)
-						_, err = to.Raw(sql, sValue, edbInfoId, eDate).Exec()
-						if err != nil {
-							return err
-						}
-					}
-				}
-			}
-		}
-		existMap[v.DataTime] = v.DataTime
-	}
-	if isAdd {
-		addSql = strings.TrimRight(addSql, ",")
-		_, err = to.Raw(addSql).Exec()
-		if err != nil {
-			return err
-		}
-	}
-	return
-}
-
 // GetBaseInfoFromZhengzhouByIndexCode 获取指标信息
 func GetBaseInfoFromZhengzhouByIndexCode(indexCode, suffix string) (list []*BaseInfoFromZz, err error) {
 	o := orm.NewOrmUsingDB("data")
@@ -373,49 +69,3 @@ func GetBaseInfoFromZhengzhouByIndexCode(indexCode, suffix string) (list []*Base
 	_, err = o.Raw(sql, indexCode).QueryRows(&list)
 	return
 }
-
-func GetZzDataByTradeCode(condition string, pars []interface{}) (item []*BaseFromZzDataSimple, err error) {
-	sql := ` SELECT * FROM base_from_trade_zhengzhou_index WHERE 1=1 `
-	o := orm.NewOrmUsingDB("data")
-	if condition != "" {
-		sql += condition
-	}
-	sql += ` ORDER BY data_time DESC `
-	_, err = o.Raw(sql, pars).QueryRows(&item)
-	return
-}
-
-func AddEdbDataZzBySql(sqlStr string) (err error) {
-	o := orm.NewOrmUsingDB("data")
-	_, err = o.Raw(sqlStr).Exec()
-	return
-}
-
-func GetEdbDataZzByCode(edbCode string) (items []*EdbInfoSearchData, err error) {
-	o := orm.NewOrmUsingDB("data")
-	sql := ` SELECT * FROM edb_data_zz WHERE edb_code=? ORDER BY data_time DESC LIMIT ? `
-	_, err = o.Raw(sql, edbCode, utils.EDB_DATA_LIMIT).QueryRows(&items)
-	return
-}
-
-func GetBaseFromZhengzhouDataAllByIndexCode(indexCode, suffix string) (list []*BaseFromTradeZhengzhouIndex, err error) {
-	o := orm.NewOrmUsingDB("data")
-	sql := `SELECT * FROM base_from_trade_zhengzhou_index WHERE %s_code=? `
-	sql = fmt.Sprintf(sql, suffix)
-	_, err = o.Raw(sql, indexCode).QueryRows(&list)
-	return
-}
-
-func GetEdbDataZzByCodeAndDate(edbCode string, startDate string) (count int, err error) {
-	o := orm.NewOrmUsingDB("data")
-	sql := ` SELECT COUNT(1) AS count FROM edb_data_zz WHERE edb_code=? AND data_time=? `
-	err = o.Raw(sql, edbCode, startDate).QueryRow(&count)
-	return
-}
-
-func ModifyEdbDataZz(edbInfoId int64, dataTime, value string) (err error) {
-	o := orm.NewOrmUsingDB("data")
-	sql := ` UPDATE edb_data_zz SET value=?,modify_time=NOW() WHERE edb_info_id=? AND data_time=? `
-	_, err = o.Raw(sql, value, edbInfoId, dataTime).Exec()
-	return
-}

+ 99 - 22
models/data_manage/edb_info.go

@@ -48,6 +48,14 @@ type EdbInfo struct {
 	ManualSave       int     `description:"是否有手动保存过上下限: 0-否; 1-是"`
 	EmptyType        int     `description:"空值处理类型(0查找前后35天,1不计算,2前值填充,3后值填充,4等于0)"`
 	MaxEmptyType     int     `description:"MAX、MIN公式空值处理类型(1、等于0;2、跳过空值)"`
+	TerminalCode     string  `description:"终端编码,用于配置在机器上"`
+	DataUpdateTime   string  `description:"最近一次数据发生变化的时间"`
+	ErDataUpdateDate string  `description:"本次更新,数据发生变化的最早日期"`
+	SourceIndexName  string  `description:"数据源中的指标名称"`
+	SubSource        int     `description:"子数据来源:0:经济数据库,1:日期序列"`
+	SubSourceName    string  `description:"子数据来源名称"`
+	IndicatorCode    string  `description:"指标代码"`
+	StockCode        string  `description:"证券代码"`
 }
 
 type EdbInfoFullClassify struct {
@@ -105,6 +113,13 @@ type EdbInfoSearch struct {
 	Unit      string `description:"单位"`
 	Frequency string `description:"频率"`
 	DataList  []*EdbInfoSearchData
+	StockList []*StockInfo `description:"时序数据"`
+}
+
+type BaseIndexInfo struct {
+	IndexName string `description:"数据日期"`
+	Unit      string `description:"单位"`
+	Frequency string `description:"频率"`
 }
 
 type EdbInfoSearchData struct {
@@ -155,7 +170,7 @@ type AddEdbInfoReq struct {
 	EndDate    string `description:"终止日期"`
 }
 
-func DeleteEdbInfoAndData(edbInfoId, source int) (err error) {
+func DeleteEdbInfoAndData(edbInfoId, source, subSource int) (err error) {
 	o := orm.NewOrmUsingDB("data")
 	to, err := o.Begin()
 	if err != nil {
@@ -177,7 +192,7 @@ func DeleteEdbInfoAndData(edbInfoId, source int) (err error) {
 	}
 
 	// 删除指标数据
-	tableName := GetEdbDataTableName(source)
+	tableName := GetEdbDataTableName(source, subSource)
 	if tableName != "" {
 		sql = ` DELETE FROM %s WHERE edb_info_id=? `
 		sql = fmt.Sprintf(sql, tableName)
@@ -291,6 +306,10 @@ type EdbInfoList struct {
 	IsEnEdb          bool                    `description:"是否展示英文标识"`
 	DataInsertConfig EdbDataInsertConfigItem `description:"指标数据插入配置"`
 	DataDateType     string                  `description:"数据日期类型,枚举值:交易日、自然日"`
+	SubSource        int                     `description:"子数据来源:0:经济数据库,1:日期序列"`
+	SubSourceName    string                  `description:"子数据来源名称"`
+	IndicatorCode    string                  `description:"指标代码"`
+	StockCode        string                  `description:"证券代码"`
 }
 
 type EdbDataInsertConfigItem struct {
@@ -322,9 +341,9 @@ func GetEdbInfoByCondition(condition string, pars []interface{}) (item *EdbInfoL
 	return
 }
 
-func GetEdbDataCountByCondition(condition string, pars []interface{}, source int) (count int, err error) {
+func GetEdbDataCountByCondition(condition string, pars []interface{}, source, subSource int) (count int, err error) {
 	o := orm.NewOrmUsingDB("data")
-	tableName := GetEdbDataTableName(source)
+	tableName := GetEdbDataTableName(source, subSource)
 	sql := ` SELECT COUNT(1) AS count FROM %s WHERE 1=1 `
 	sql = fmt.Sprintf(sql, tableName)
 	if condition != "" {
@@ -334,9 +353,9 @@ func GetEdbDataCountByCondition(condition string, pars []interface{}, source int
 	return
 }
 
-func GetEdbDataListByCondition(condition string, pars []interface{}, source, pageSize, startSize int) (item []*EdbData, err error) {
+func GetEdbDataListByCondition(condition string, pars []interface{}, source, subSource, pageSize, startSize int) (item []*EdbData, err error) {
 	o := orm.NewOrmUsingDB("data")
-	tableName := GetEdbDataTableName(source)
+	tableName := GetEdbDataTableName(source, subSource)
 	sql := ` SELECT * FROM %s WHERE 1=1 `
 	sql = fmt.Sprintf(sql, tableName)
 
@@ -350,9 +369,9 @@ func GetEdbDataListByCondition(condition string, pars []interface{}, source, pag
 }
 
 // GetAllEdbDataListByCondition 根据条件获取所有的数据
-func GetAllEdbDataListByCondition(condition string, pars []interface{}, source int) (item []*EdbData, err error) {
+func GetAllEdbDataListByCondition(condition string, pars []interface{}, source, subSource int) (item []*EdbData, err error) {
 	o := orm.NewOrmUsingDB("data")
-	tableName := GetEdbDataTableName(source)
+	tableName := GetEdbDataTableName(source, subSource)
 	sql := ` SELECT * FROM %s WHERE 1=1 `
 	sql = fmt.Sprintf(sql, tableName)
 
@@ -459,10 +478,10 @@ type EdbInfoMaxAndMinInfo struct {
 	LatestValue float64 `description:"最新值"`
 }
 
-func GetEdbInfoMaxAndMinInfo(source int, edbCode string) (item *EdbInfoMaxAndMinInfo, err error) {
+func GetEdbInfoMaxAndMinInfo(source, subSource int, edbCode string) (item *EdbInfoMaxAndMinInfo, err error) {
 	o := orm.NewOrmUsingDB("data")
 	sql := ``
-	tableName := GetEdbDataTableName(source)
+	tableName := GetEdbDataTableName(source, subSource)
 	sql = ` SELECT MIN(data_time) AS min_date,MAX(data_time) AS max_date,MIN(value) AS min_value,MAX(value) AS max_value FROM %s WHERE edb_code=? `
 	sql = fmt.Sprintf(sql, tableName)
 	err = o.Raw(sql, edbCode).QueryRow(&item)
@@ -497,10 +516,10 @@ func GetEdbInfoFilter(condition string, pars []interface{}) (list []*EdbInfoList
 }
 
 //order:1升序,其余值为降序
-func GetEdbDataListAll(condition string, pars []interface{}, source, order int) (item []*EdbInfoSearchData, err error) {
+func GetEdbDataListAll(condition string, pars []interface{}, source, subSource, order int) (item []*EdbInfoSearchData, err error) {
 	o := orm.NewOrmUsingDB("data")
 	sql := ``
-	tableName := GetEdbDataTableName(source)
+	tableName := GetEdbDataTableName(source, subSource)
 	sql = ` SELECT * FROM %s WHERE 1=1 `
 	sql = fmt.Sprintf(sql, tableName)
 
@@ -517,10 +536,10 @@ func GetEdbDataListAll(condition string, pars []interface{}, source, order int)
 }
 
 // GetLastEdbData 获取最近的一条指标数据
-func GetLastEdbData(condition string, pars []interface{}, source int) (item *EdbInfoSearchData, err error) {
+func GetLastEdbData(condition string, pars []interface{}, source, subSource int) (item *EdbInfoSearchData, err error) {
 	o := orm.NewOrmUsingDB("data")
 	sql := ``
-	tableName := GetEdbDataTableName(source)
+	tableName := GetEdbDataTableName(source, subSource)
 	sql = ` SELECT * FROM %s WHERE 1=1 `
 	sql = fmt.Sprintf(sql, tableName)
 
@@ -533,10 +552,10 @@ func GetLastEdbData(condition string, pars []interface{}, source int) (item *Edb
 }
 
 //order:1升序,其余值为降序
-func GetEdbDataCount(condition string, pars []interface{}, source int) (count int, err error) {
+func GetEdbDataCount(condition string, pars []interface{}, source, subSource int) (count int, err error) {
 	o := orm.NewOrmUsingDB("data")
 	sql := ``
-	tableName := GetEdbDataTableName(source)
+	tableName := GetEdbDataTableName(source, subSource)
 	sql = ` SELECT COUNT(1) AS count FROM %s WHERE 1=1 `
 	sql = fmt.Sprintf(sql, tableName)
 
@@ -564,9 +583,10 @@ func ModifyCalculateEdbInfo(item *EditEdbInfoReq) (err error) {
 }
 
 type AddEdbInfoResp struct {
-	EdbInfoId  int    `description:"指标ID"`
-	UniqueCode string `description:"指标唯一编码"`
-	ClassifyId int    `description:"分类id"`
+	EdbInfoId    int      `description:"指标ID"`
+	UniqueCode   string   `description:"指标唯一编码"`
+	ClassifyId   int      `description:"分类id"`
+	ExistEdbName []string `description:"重复指标名称"`
 }
 
 // 根据基础指标获取所有关联指标
@@ -718,10 +738,10 @@ func GetRefreshEdbInfoFromBase(edbInfoId, source int) (baseEdbInfoArr, calculate
 	return
 }
 
-func ModifyEdbInfoDataStatus(edbInfoId int64, source int, edbCode string) (err error) {
+func ModifyEdbInfoDataStatus(edbInfoId int64, source, subSource int, edbCode string) (err error) {
 	o := orm.NewOrmUsingDB("data")
 	sql := ``
-	tableName := GetEdbDataTableName(source)
+	tableName := GetEdbDataTableName(source, subSource)
 	sql = ` UPDATE %s SET edb_info_id=?,modify_time=NOW() WHERE edb_code=? `
 	sql = fmt.Sprintf(sql, tableName)
 	_, err = o.Raw(sql, edbInfoId, edbCode).Exec()
@@ -945,6 +965,7 @@ func replaceRelationEdbInfo(mappingList []*EdbInfoCalculateMapping, oldEdbInfo,
 			uniqueCode := edbInfo.UniqueCode
 			sourName := edbInfo.SourceName
 			source := edbInfo.Source
+			subSource := edbInfo.SubSource
 			edbInfoId := edbInfo.EdbInfoId
 
 			req := new(EdbInfoCalculateBatchSaveReq)
@@ -1195,7 +1216,7 @@ func replaceRelationEdbInfo(mappingList []*EdbInfoCalculateMapping, oldEdbInfo,
 				err = fmt.Errorf("无效计算方式,source:" + strconv.Itoa(source))
 				return
 			}
-			maxAndMinItem, tmpErr := GetEdbInfoMaxAndMinInfo(source, edbCode)
+			maxAndMinItem, tmpErr := GetEdbInfoMaxAndMinInfo(source, subSource, edbCode)
 			err = tmpErr
 			if err != nil && err.Error() != utils.ErrNoRow() {
 				errmsg = "生成" + sourName + "失败,GetEdbInfoMaxAndMinInfo Err:" + err.Error()
@@ -1555,3 +1576,59 @@ func GetEdbInfoAdminList(edbType int) (list []int, err error) {
 	_, err = o.Raw(sql, edbType).QueryRows(&list)
 	return
 }
+
+type StockInfo struct {
+	StockCode string
+	EdbCode   string
+	DataList  []*EdbInfoSearchData
+}
+
+type BatchAddEdbInfoReq struct {
+	BatchList []*BatchAddEdbInfo
+}
+
+type BatchAddEdbInfo struct {
+	Source     int    `description:"来源id"`
+	EdbName    string `description:"指标名称"`
+	Frequency  string `description:"频率"`
+	Unit       string `description:"单位"`
+	ClassifyId int    `description:"分类id"`
+	StockCode  string `description:"证券代码"`
+	EdbCode    string `description:"指标编码"`
+}
+
+func GetEdbInfoWsdMaxAndMinInfo(source, subSource int, edbCode string) (item *EdbInfoMaxAndMinInfo, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ``
+	tableName := GetEdbDataTableNameAndSubSource(source, subSource)
+	sql = ` SELECT MIN(data_time) AS min_date,MAX(data_time) AS max_date,MIN(value) AS min_value,MAX(value) AS max_value FROM %s WHERE edb_code=? `
+	sql = fmt.Sprintf(sql, tableName)
+	err = o.Raw(sql, edbCode).QueryRow(&item)
+	if err != nil {
+		return
+	}
+
+	var latest_value float64
+	sql = ` SELECT value AS latest_value FROM %s WHERE edb_code=? ORDER BY data_time DESC LIMIT 1 `
+	sql = fmt.Sprintf(sql, tableName)
+	err = o.Raw(sql, edbCode).QueryRow(&latest_value)
+	item.LatestValue = latest_value
+	return
+}
+
+// GetEdbInfoByNames 根据名称获取普通的指标
+func GetEdbInfoByNames(edbNames string) (items []*EdbInfoList, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT * FROM edb_info WHERE edb_name IN (` + edbNames + `) AND edb_info_type = 0 `
+	_, err = o.Raw(sql).QueryRows(&items)
+	return
+}
+
+type EdbInfoExistCheckResp struct {
+	IndexExist        bool       `description:"指标是否存在:true,存在,false:不存在"`
+	ExistStockCodeArr []string   `description:"存在的证券代码"`
+	ExistEdbCodeArr   []string   `description:"存在的指标代码"`
+	ExistClassifyId   []int      `description:"存在的分类id"`
+	ExistIndexId      []int      `description:"存在的指标id"`
+	ExistEdbInfo      []*EdbInfo `description:"存在的指标"`
+}

+ 1 - 167
models/data_manage/edb_info_calculate.go

@@ -238,172 +238,6 @@ func GetEdbInfoCalculateMap(edbInfoId, source int) (list []*EdbInfo, err error)
 	return
 }
 
-// 指标运算
-func AddCalculate(req *EdbInfoCalculateBatchSaveReq, fromEdbInfo []*EdbInfoCalculateDetail, edbCode, uniqueCode, formulaStr string, sysUserId int, sysUserRealName string) (edbInfoId int, err error) {
-	o := orm.NewOrmUsingDB("data")
-	to, err := o.Begin()
-	if err != nil {
-		return
-	}
-	defer func() {
-		if err != nil {
-			_ = to.Rollback()
-		} else {
-			_ = to.Commit()
-		}
-	}()
-	if req.EdbInfoId <= 0 {
-		edbInfo := new(EdbInfo)
-		edbInfo.Source = utils.DATA_SOURCE_CALCULATE
-		edbInfo.SourceName = "指标运算"
-		edbInfo.EdbCode = edbCode
-		edbInfo.EdbName = req.EdbName
-		edbInfo.EdbNameSource = req.EdbName
-		edbInfo.Frequency = req.Frequency
-		edbInfo.Unit = req.Unit
-		edbInfo.ClassifyId = req.ClassifyId
-		edbInfo.SysUserId = sysUserId
-		edbInfo.SysUserRealName = sysUserRealName
-		edbInfo.CreateTime = time.Now()
-		edbInfo.ModifyTime = time.Now()
-		edbInfo.UniqueCode = uniqueCode
-		edbInfo.CalculateFormula = req.CalculateFormula
-		edbInfo.EdbType = 2
-		newEdbInfoId, err := to.Insert(edbInfo)
-		if err != nil {
-			return int(newEdbInfoId), err
-		}
-		edbInfoId = int(newEdbInfoId)
-		//处理同名指标
-		{
-			edbNameList, err := GetEdbInfoByName(req.EdbName)
-			if err != nil {
-				return edbInfoId, err
-			}
-			if len(edbNameList) >= 2 {
-				for _, v := range edbNameList {
-					edbName := v.EdbName + "(" + v.SourceName + ")"
-					err = ModifyEdbInfoNameSource(edbName, v.EdbInfoId)
-					if err != nil {
-						return edbInfoId, err
-					}
-				}
-			}
-		}
-
-		//calculateList := make([]*EdbInfoCalculate, 0)
-		edbInfoList := make([]*EdbInfo, 0)
-
-		for _, v := range req.EdbInfoIdArr {
-			edbInfo, err := GetEdbInfoById(v.EdbInfoId)
-			if err != nil {
-				return edbInfoId, err
-			}
-			//calculateItem := new(EdbInfoCalculate)
-			//calculateItem.CreateTime = time.Now()
-			//calculateItem.ModifyTime = time.Now()
-			//calculateItem.Sort = k + 1
-			//calculateItem.EdbCode = edbCode
-			//calculateItem.EdbInfoId = int(edbInfoId)
-			//calculateItem.FromEdbInfoId = edbInfo.EdbInfoId
-			//calculateItem.FromEdbCode = edbInfo.EdbCode
-			//calculateItem.FromEdbName = edbInfo.EdbName
-			//calculateItem.FromSource = edbInfo.Source
-			//calculateItem.FromSourceName = edbInfo.SourceName
-			//calculateItem.FromTag = v.FromTag
-			//calculateList = append(calculateList, calculateItem)
-			edbInfoList = append(edbInfoList, edbInfo)
-		}
-		//if len(calculateList) > 0 {
-		//	_, err = to.InsertMulti(1, calculateList)
-		//	if err != nil {
-		//		return edbInfoId, err
-		//	}
-		//}
-	} else {
-		edbInfoId = req.EdbInfoId
-		dataTableName := GetEdbDataTableName(utils.DATA_SOURCE_CALCULATE)
-		deleteSql := ` DELETE FROM %s WHERE edb_info_id=? `
-		deleteSql = fmt.Sprintf(deleteSql, dataTableName)
-		_, err = to.Raw(deleteSql, req.EdbInfoId).Exec()
-	}
-	//计算数据
-	saveDataMap := make(map[string]map[int]float64)
-	for _, v := range fromEdbInfo {
-		var condition string
-		var pars []interface{}
-		condition += " AND edb_info_id=? "
-		pars = append(pars, v.FromEdbInfoId)
-		dataList, err := GetEdbDataListAll(condition, pars, v.FromSource, 1)
-		if err != nil {
-			return edbInfoId, err
-		}
-		dataMap := make(map[string]float64)
-		for _, dv := range dataList {
-			if val, ok := saveDataMap[dv.DataTime]; ok {
-				if _, ok := val[v.EdbInfoId]; !ok {
-					val[v.EdbInfoId] = dv.Value
-				}
-			} else {
-				temp := make(map[int]float64)
-				temp[v.EdbInfoId] = dv.Value
-				saveDataMap[dv.DataTime] = temp
-			}
-		}
-		item := new(CalculateItems)
-		item.EdbInfoId = v.EdbInfoId
-		item.DataMap = dataMap
-	}
-
-	//formulaMap := CheckFormula(formulaStr)
-	//addSql := ` INSERT INTO edb_data_calculate(edb_info_id,edb_code,data_time,value,create_time,modify_time,status,data_timestamp) values `
-	//nowStr := time.Now().Format(utils.FormatDateTime)
-	//var isAdd bool
-	//
-	//for sk, sv := range saveDataMap {
-	//	formulaStr = strings.ToUpper(formulaStr)
-	//	formulaFormStr := ReplaceFormula(edbInfoIdArr, sv, formulaMap, formulaStr, edbInfoIdBytes)
-	//	if formulaFormStr != "" {
-	//		utils.FileLog.Info("formulaFormStr:%s", formulaFormStr)
-	//		expression := formula.NewExpression(formulaFormStr)
-	//		calResult, err := expression.Evaluate()
-	//		if err != nil {
-	//			err = errors.New("计算失败:Err:" + err.Error() + ";formulaStr:" + formulaFormStr)
-	//			fmt.Println(err)
-	//			return err
-	//		}
-	//		calVal, err := calResult.Float64()
-	//		if err != nil {
-	//			err = errors.New("计算失败:获取计算值失败 Err:" + err.Error() + ";formulaStr:" + formulaFormStr)
-	//			fmt.Println(err)
-	//			return err
-	//		}
-	//
-	//		//需要存入的数据
-	//		{
-	//			dataTime, _ := time.Parse(utils.FormatDate, sk)
-	//			timestamp := dataTime.UnixNano() / 1e6
-	//			timeStr := fmt.Sprintf("%d", timestamp)
-	//			addSql += "("
-	//			addSql += strconv.Itoa(edbInfoId) + "," + "'" + edbCode + "'" + "," + "'" + sk + "'" + "," + utils.SubFloatToString(calVal, 4) + "," + "'" + nowStr + "'" +
-	//				"," + "'" + nowStr + "'" + "," + "1"
-	//			addSql += "," + "'" + timeStr + "'"
-	//			addSql += "),"
-	//			isAdd = true
-	//		}
-	//	}
-	//}
-	//if isAdd {
-	//	addSql = strings.TrimRight(addSql, ",")
-	//	AddEdbDataCalculateBySql(addSql)
-	//	if err != nil {
-	//		fmt.Println("AddEdbDataCalculate Err:" + err.Error())
-	//		return
-	//	}
-	//}
-	return
-}
-
 type CalculateItems struct {
 	EdbInfoId int
 	DataMap   map[string]float64
@@ -567,7 +401,7 @@ func Calculate(edbInfoIdArr []*EdbInfo, edbInfoId int, edbCode, formulaStr strin
 		var pars []interface{}
 		condition += " AND edb_info_id=? "
 		pars = append(pars, v.EdbInfoId)
-		dataList, err := GetEdbDataListAll(condition, pars, v.Source, 1)
+		dataList, err := GetEdbDataListAll(condition, pars, v.Source, v.SubSource, 1)
 		if err != nil {
 			return err
 		}

+ 2 - 2
models/data_manage/edb_info_calculate_bp.go

@@ -71,7 +71,7 @@ func AddCalculateBp(req *EdbInfoCalculateBatchSaveReq, fromEdbInfo *EdbInfo, edb
 		}
 	} else {
 		edbInfoId = req.EdbInfoId
-		dataTableName := GetEdbDataTableName(utils.DATA_SOURCE_CALCULATE_BP)
+		dataTableName := GetEdbDataTableName(utils.DATA_SOURCE_CALCULATE_BP, utils.DATA_SUB_SOURCE_EDB)
 		fmt.Println("dataTableName:" + dataTableName)
 		deleteSql := ` DELETE FROM %s WHERE edb_info_id=? `
 		deleteSql = fmt.Sprintf(deleteSql, dataTableName)
@@ -92,7 +92,7 @@ func AddCalculateBp(req *EdbInfoCalculateBatchSaveReq, fromEdbInfo *EdbInfo, edb
 	} else {
 		pars = append(pars, fromEdbInfo.EdbInfoId)
 	}
-	dataList, err := GetEdbDataListAll(condition, pars, fromEdbInfo.Source, 0)
+	dataList, err := GetEdbDataListAll(condition, pars, fromEdbInfo.Source, fromEdbInfo.SubSource, 0)
 	if err != nil {
 		return edbInfoId, err
 	}

+ 2 - 2
models/data_manage/edb_info_calculate_hbz.go

@@ -72,7 +72,7 @@ func AddCalculateHbz(req *EdbInfoCalculateBatchSaveReq, fromEdbInfo *EdbInfo, ed
 		}
 	} else {
 		edbInfoId = req.EdbInfoId
-		dataTableName := GetEdbDataTableName(utils.DATA_SOURCE_CALCULATE_HBZ)
+		dataTableName := GetEdbDataTableName(utils.DATA_SOURCE_CALCULATE_HBZ, utils.DATA_SUB_SOURCE_EDB)
 		deleteSql := ` DELETE FROM %s WHERE edb_info_id=? `
 		deleteSql = fmt.Sprintf(deleteSql, dataTableName)
 		_, err = to.Raw(deleteSql, req.EdbInfoId).Exec()
@@ -89,7 +89,7 @@ func AddCalculateHbz(req *EdbInfoCalculateBatchSaveReq, fromEdbInfo *EdbInfo, ed
 	} else {
 		pars = append(pars, fromEdbInfo.EdbInfoId)
 	}
-	dataList, err := GetEdbDataListAll(condition, pars, fromEdbInfo.Source, 0)
+	dataList, err := GetEdbDataListAll(condition, pars, fromEdbInfo.Source, fromEdbInfo.SubSource, 0)
 	if err != nil {
 		return edbInfoId, err
 	}

+ 2 - 2
models/data_manage/edb_info_calculate_hcz.go

@@ -72,7 +72,7 @@ func AddCalculateHcz(req *EdbInfoCalculateBatchSaveReq, fromEdbInfo *EdbInfo, ed
 		}
 	} else {
 		edbInfoId = req.EdbInfoId
-		dataTableName := GetEdbDataTableName(utils.DATA_SOURCE_CALCULATE_HCZ)
+		dataTableName := GetEdbDataTableName(utils.DATA_SOURCE_CALCULATE_HCZ, utils.DATA_SUB_SOURCE_EDB)
 		deleteSql := ` DELETE FROM %s WHERE edb_info_id=? `
 		deleteSql = fmt.Sprintf(deleteSql, dataTableName)
 		_, err = to.Raw(deleteSql, req.EdbInfoId).Exec()
@@ -89,7 +89,7 @@ func AddCalculateHcz(req *EdbInfoCalculateBatchSaveReq, fromEdbInfo *EdbInfo, ed
 	} else {
 		pars = append(pars, fromEdbInfo.EdbInfoId)
 	}
-	dataList, err := GetEdbDataListAll(condition, pars, fromEdbInfo.Source, 0)
+	dataList, err := GetEdbDataListAll(condition, pars, fromEdbInfo.Source, fromEdbInfo.SubSource, 0)
 	if err != nil {
 		return edbInfoId, err
 	}

+ 8 - 8
models/data_manage/edb_info_calculate_ljztbpj.go

@@ -77,7 +77,7 @@ func EditCalculateLjztbpj(req *EdbInfoCalculateBatchEditReq, nowEdbInfo, firstEd
 				}
 
 				//如果拼接指标变更了,那么需要删除所有的指标数据
-				tableName := GetEdbDataTableName(nowEdbInfo.Source)
+				tableName := GetEdbDataTableName(nowEdbInfo.Source, nowEdbInfo.SubSource)
 				sql = fmt.Sprintf(` DELETE FROM %s WHERE edb_info_id = ? `, tableName)
 
 				_, err = to.Raw(sql, edbInfoId).Exec()
@@ -117,7 +117,7 @@ func EditCalculateLjztbpj(req *EdbInfoCalculateBatchEditReq, nowEdbInfo, firstEd
 			pars = append(pars, "%12-31", firstEdbInfo.EdbInfoId)
 
 			//获取最新的待拼接指标
-			lastEdbData, tmpErr := GetLastEdbData(condition, pars, firstEdbInfo.Source)
+			lastEdbData, tmpErr := GetLastEdbData(condition, pars, firstEdbInfo.Source, firstEdbInfo.SubSource)
 			if tmpErr != nil {
 				return edbInfoId, tmpErr
 			}
@@ -129,7 +129,7 @@ func EditCalculateLjztbpj(req *EdbInfoCalculateBatchEditReq, nowEdbInfo, firstEd
 			condition += " AND data_time <= ? AND edb_info_id=? "
 			pars = append(pars, lastEdbData.DataTime, firstEdbInfo.EdbInfoId)
 
-			firstDataList, tmpErr := GetEdbDataListAll(condition, pars, firstEdbInfo.Source, 0)
+			firstDataList, tmpErr := GetEdbDataListAll(condition, pars, firstEdbInfo.Source, firstEdbInfo.SubSource, 0)
 			if tmpErr != nil {
 				return edbInfoId, tmpErr
 			}
@@ -148,7 +148,7 @@ func EditCalculateLjztbpj(req *EdbInfoCalculateBatchEditReq, nowEdbInfo, firstEd
 			condition += " AND edb_info_id=? and data_time <= ?"
 			pars = append(pars, nowEdbInfo.EdbInfoId, nowEdbInfo.CalculateFormula)
 
-			nowEdbDataList, tmpErr := GetEdbDataListAll(condition, pars, nowEdbInfo.Source, 0)
+			nowEdbDataList, tmpErr := GetEdbDataListAll(condition, pars, nowEdbInfo.Source, nowEdbInfo.SubSource, 0)
 			if tmpErr != nil {
 				return edbInfoId, tmpErr
 			}
@@ -180,7 +180,7 @@ func EditCalculateLjztbpj(req *EdbInfoCalculateBatchEditReq, nowEdbInfo, firstEd
 				}
 
 				//如果同比值指标变更了,那么需要删除所有计算出来的指标数据
-				tableName := GetEdbDataTableName(nowEdbInfo.Source)
+				tableName := GetEdbDataTableName(nowEdbInfo.Source, nowEdbInfo.SubSource)
 				sql = fmt.Sprintf(` DELETE FROM %s WHERE edb_info_id = ? and data_time > ? `, tableName)
 
 				_, err = to.Raw(sql, edbInfoId, nowEdbInfo.CalculateFormula).Exec()
@@ -220,7 +220,7 @@ func EditCalculateLjztbpj(req *EdbInfoCalculateBatchEditReq, nowEdbInfo, firstEd
 		pars = append(pars, lastDateTime, secondEdbInfo.EdbInfoId)
 
 		//同比值指标的数据列表
-		secondDataList, tmpErr := GetEdbDataListAll(condition, pars, secondEdbInfo.Source, 0)
+		secondDataList, tmpErr := GetEdbDataListAll(condition, pars, secondEdbInfo.Source, secondEdbInfo.SubSource, 0)
 		if tmpErr != nil {
 			return edbInfoId, tmpErr
 		}
@@ -343,7 +343,7 @@ func EditCalculateLjztbpj(req *EdbInfoCalculateBatchEditReq, nowEdbInfo, firstEd
 			removeDateStr := strings.Join(removeDateList, `","`)
 			removeDateStr = `"` + removeDateStr + `"`
 			//如果拼接指标变更了,那么需要删除所有的指标数据
-			tableName := GetEdbDataTableName(nowEdbInfo.Source)
+			tableName := GetEdbDataTableName(nowEdbInfo.Source, nowEdbInfo.SubSource)
 			sql = fmt.Sprintf(` DELETE FROM %s WHERE edb_info_id = ? and data_time in (%s) `, tableName, removeDateStr)
 
 			_, err = to.Raw(sql, edbInfoId).Exec()
@@ -356,7 +356,7 @@ func EditCalculateLjztbpj(req *EdbInfoCalculateBatchEditReq, nowEdbInfo, firstEd
 
 	//修改现有的数据中对应的值
 	{
-		tableName := GetEdbDataTableName(nowEdbInfo.Source)
+		tableName := GetEdbDataTableName(nowEdbInfo.Source, nowEdbInfo.SubSource)
 		for edbDate, edbDataValue := range updateEdbDataMap {
 			sql = fmt.Sprintf(` UPDATE  %s set value = %f,modify_time=now() WHERE edb_info_id = ? and data_time = %s `, tableName, edbDataValue, edbDate)
 

+ 2 - 2
models/data_manage/edb_info_calculate_ljzzy.go

@@ -86,7 +86,7 @@ func AddCalculateLjzzy(req *EdbInfoCalculateBatchSaveReq, fromEdbInfo *EdbInfo,
 		}
 	} else {
 		edbInfoId = req.EdbInfoId
-		dataTableName := GetEdbDataTableName(utils.DATA_SOURCE_CALCULATE_LJZZY)
+		dataTableName := GetEdbDataTableName(utils.DATA_SOURCE_CALCULATE_LJZZY, utils.DATA_SUB_SOURCE_EDB)
 		deleteSql := ` DELETE FROM %s WHERE edb_info_id=? `
 		deleteSql = fmt.Sprintf(deleteSql, dataTableName)
 		_, err = to.Raw(deleteSql, req.EdbInfoId).Exec()
@@ -102,7 +102,7 @@ func AddCalculateLjzzy(req *EdbInfoCalculateBatchSaveReq, fromEdbInfo *EdbInfo,
 		pars = append(pars, fromEdbInfo.EdbInfoId)
 	}
 	fmt.Println("EdbInfoId:", req.FromEdbInfoId)
-	dataList, err := GetEdbDataListAll(condition, pars, fromEdbInfo.Source, 1)
+	dataList, err := GetEdbDataListAll(condition, pars, fromEdbInfo.Source, fromEdbInfo.SubSource, 1)
 	if err != nil {
 		return edbInfoId, err
 	}

+ 2 - 2
models/data_manage/edb_info_calculate_nszydpjjs.go

@@ -87,7 +87,7 @@ func AddCalculateNszydpjjs(req *EdbInfoCalculateBatchSaveReq, fromEdbInfo *EdbIn
 		}
 	} else {
 		edbInfoId = req.EdbInfoId
-		dataTableName := GetEdbDataTableName(utils.DATA_SOURCE_CALCULATE_NSZYDPJJS)
+		dataTableName := GetEdbDataTableName(utils.DATA_SOURCE_CALCULATE_NSZYDPJJS, utils.DATA_SUB_SOURCE_EDB)
 		deleteSql := ` DELETE FROM %s WHERE edb_info_id=? `
 		deleteSql = fmt.Sprintf(deleteSql, dataTableName)
 		_, err = to.Raw(deleteSql, req.EdbInfoId).Exec()
@@ -103,7 +103,7 @@ func AddCalculateNszydpjjs(req *EdbInfoCalculateBatchSaveReq, fromEdbInfo *EdbIn
 	} else {
 		pars = append(pars, fromEdbInfo.EdbInfoId)
 	}
-	dataList, err := GetEdbDataListAll(condition, pars, fromEdbInfo.Source, 0)
+	dataList, err := GetEdbDataListAll(condition, pars, fromEdbInfo.Source, fromEdbInfo.SubSource, 0)
 	if err != nil {
 		return edbInfoId, err
 	}

+ 4 - 259
models/data_manage/edb_info_calculate_tbz.go

@@ -105,7 +105,7 @@ func AddCalculateTbz(req *EdbInfoCalculateBatchSaveReq, fromEdbInfo *EdbInfo, ed
 
 	} else {
 		edbInfoId = req.EdbInfoId
-		dataTableName := GetEdbDataTableName(utils.DATA_SOURCE_CALCULATE_TBZ)
+		dataTableName := GetEdbDataTableName(utils.DATA_SOURCE_CALCULATE_TBZ, utils.DATA_SUB_SOURCE_EDB)
 		deleteSql := ` DELETE FROM %s WHERE edb_info_id=? `
 		deleteSql = fmt.Sprintf(deleteSql, dataTableName)
 		_, err = to.Raw(deleteSql, req.EdbInfoId).Exec()
@@ -122,7 +122,7 @@ func AddCalculateTbz(req *EdbInfoCalculateBatchSaveReq, fromEdbInfo *EdbInfo, ed
 	} else {
 		pars = append(pars, fromEdbInfo.EdbInfoId)
 	}
-	dataList, err := GetEdbDataListAll(condition, pars, fromEdbInfo.Source, 0)
+	dataList, err := GetEdbDataListAll(condition, pars, fromEdbInfo.Source, fromEdbInfo.SubSource, 0)
 	if err != nil {
 		return edbInfoId, err
 	}
@@ -391,7 +391,7 @@ func EditCalculateTbz(req *EdbInfoCalculateBatchEditReq, fromEdbInfo *EdbInfo, e
 		condition += " AND edb_info_id=? "
 		pars = append(pars, req.FromEdbInfoId)
 		fmt.Println("EdbInfoId:", req.FromEdbInfoId)
-		dataList, err := GetEdbDataListAll(condition, pars, fromEdbInfo.Source, 0)
+		dataList, err := GetEdbDataListAll(condition, pars, fromEdbInfo.Source, fromEdbInfo.SubSource, 0)
 		if err != nil {
 			return edbInfoId, err
 		}
@@ -558,7 +558,7 @@ func RefreshCalculateTbz(edbInfoId int, fromEdbInfo *EdbInfo, edbCode, startDate
 		pars = append(pars, endDate)
 	}
 
-	dataList, err := GetEdbDataListAll(condition, pars, fromEdbInfo.Source, 0)
+	dataList, err := GetEdbDataListAll(condition, pars, fromEdbInfo.Source, fromEdbInfo.SubSource, 0)
 	if err != nil {
 		return err
 	}
@@ -785,258 +785,3 @@ func ModifyEdbDataCalculateTbz(edbInfoId int64, dataTime, value string) (err err
 	_, err = o.Raw(sql, value, edbInfoId, dataTime).Exec()
 	return
 }
-
-// 刷新所有同比值数据
-func RefreshAllCalculateTbz(edbInfoId, source int, fromEdbInfo *EdbInfo, edbCode, startDate, endDate string) (err error) {
-	o := orm.NewOrmUsingDB("data")
-	to, err := o.Begin()
-	if err != nil {
-		return
-	}
-	defer func() {
-		if err != nil {
-			_ = to.Rollback()
-		} else {
-			_ = to.Commit()
-		}
-	}()
-
-	if err != nil {
-		return
-	}
-	edbInfoIdStr := strconv.Itoa(edbInfoId)
-	//计算数据
-
-	//计算数据
-	var condition string
-	var pars []interface{}
-	condition += " AND edb_info_id=? "
-	pars = append(pars, fromEdbInfo.EdbInfoId)
-
-	if startDate != "" {
-		condition += " AND data_time>=? "
-		pars = append(pars, startDate)
-	}
-	if endDate != "" {
-		condition += " AND data_time<=? "
-		pars = append(pars, endDate)
-	}
-
-	dataList, err := GetEdbDataListAll(condition, pars, fromEdbInfo.Source, 0)
-	if err != nil {
-		return err
-	}
-	var dateArr []string
-	dataMap := make(map[string]*EdbInfoSearchData)
-	for _, v := range dataList {
-		dateArr = append(dateArr, v.DataTime)
-		dataMap[v.DataTime] = v
-	}
-	fmt.Println("source:", source)
-	//获取指标所有数据
-	existDataList := make([]*EdbDataBase, 0)
-	dataTableName := GetEdbDataTableName(source)
-	fmt.Println("dataTableName:", dataTableName)
-	sql := `SELECT * FROM %s WHERE edb_info_id=? `
-	sql = fmt.Sprintf(sql, dataTableName)
-	_, err = to.Raw(sql, edbInfoId).QueryRows(&existDataList)
-	if err != nil {
-		return err
-	}
-	existDataMap := make(map[string]string)
-	for _, v := range existDataList {
-		existDataMap[v.DataTime] = v.Value
-	}
-	fmt.Println("existDataMap:", existDataMap)
-	addSql := ` INSERT INTO edb_data_calculate_tbz(edb_info_id,edb_code,data_time,value,create_time,modify_time,status,data_timestamp) values `
-	var isAdd bool
-	existAddDataMap := make(map[string]string)
-	for _, av := range dateArr {
-		currentItem := dataMap[av]
-		if currentItem != nil {
-			//当前日期
-			currentDate, err := time.Parse(utils.FormatDate, av)
-			if err != nil {
-				return err
-			}
-			//上一年的日期
-			preDate := currentDate.AddDate(-1, 0, 0)
-			preDateStr := preDate.Format(utils.FormatDate)
-			if findItem, ok := dataMap[preDateStr]; ok { //上一年同期找到
-				//dataTime, _ := time.Parse(utils.FormatDate, date)
-				timestamp := currentDate.UnixNano() / 1e6
-				timestampStr := fmt.Sprintf("%d", timestamp)
-				val := TbzDiv(currentItem.Value, findItem.Value)
-				if existVal, ok := existDataMap[av]; !ok {
-					if _, existOk := existAddDataMap[av]; !existOk {
-						addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
-						isAdd = true
-					}
-					existAddDataMap[av] = av
-				} else {
-					if existVal != val {
-						sql := ` UPDATE %s SET value=?,modify_time=NOW() WHERE edb_info_id=? AND data_time=? `
-						sql = fmt.Sprintf(sql, dataTableName)
-						_, err = to.Raw(sql, val, edbInfoId, av).Exec()
-						if err != nil {
-							return err
-						}
-					}
-				}
-				continue
-			} else {
-				if fromEdbInfo.Frequency == "月度" { //向上和向下,各找一个月
-					for i := 0; i <= 35; i++ {
-						nextDateDay := preDate.AddDate(0, 0, i)
-						nextDateDayStr := nextDateDay.Format(utils.FormatDate)
-						if findItem, ok := dataMap[nextDateDayStr]; ok { //上一年同期->下一个月找到
-							timestamp := currentDate.UnixNano() / 1e6
-							timestampStr := fmt.Sprintf("%d", timestamp)
-							val := TbzDiv(currentItem.Value, findItem.Value)
-
-							if existVal, ok := existDataMap[av]; !ok {
-								if _, existOk := existAddDataMap[av]; !existOk {
-									addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
-									isAdd = true
-								}
-								existAddDataMap[av] = av
-							} else {
-								if existVal != val {
-									sql := ` UPDATE %s SET value=?,modify_time=NOW() WHERE edb_info_id=? AND data_time=? `
-									sql = fmt.Sprintf(sql, dataTableName)
-									_, err = to.Raw(sql, val, edbInfoId, av).Exec()
-									if err != nil {
-										return err
-									}
-								}
-							}
-							break
-						} else {
-							preDateDay := preDate.AddDate(0, 0, -i)
-							preDateDayStr := preDateDay.Format(utils.FormatDate)
-							if findItem, ok := dataMap[preDateDayStr]; ok { //上一年同期->上一个月找到
-								timestamp := currentDate.UnixNano() / 1e6
-								timestampStr := fmt.Sprintf("%d", timestamp)
-								val := TbzDiv(currentItem.Value, findItem.Value)
-
-								if existVal, ok := existDataMap[av]; !ok {
-									if _, existOk := existAddDataMap[av]; !existOk {
-										addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
-										isAdd = true
-									}
-									existAddDataMap[av] = av
-								} else {
-									if existVal != val {
-										sql := ` UPDATE %s SET value=?,modify_time=NOW() WHERE edb_info_id=? AND data_time=? `
-										sql = fmt.Sprintf(sql, dataTableName)
-										_, err = to.Raw(sql, val, edbInfoId, av).Exec()
-										if err != nil {
-											return err
-										}
-									}
-								}
-								break
-							}
-						}
-					}
-				} else if fromEdbInfo.Frequency == "季度" || fromEdbInfo.Frequency == "年度" {
-					if findItem, ok := dataMap[preDateStr]; ok { //上一年同期->下一个月找到
-						timestamp := currentDate.UnixNano() / 1e6
-						timestampStr := fmt.Sprintf("%d", timestamp)
-						val := TbzDiv(currentItem.Value, findItem.Value)
-
-						if existVal, ok := existDataMap[av]; !ok {
-							if _, existOk := existAddDataMap[av]; !existOk {
-								addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
-								isAdd = true
-							}
-							existAddDataMap[av] = av
-						} else {
-							if existVal != val {
-								sql := ` UPDATE %s SET value=?,modify_time=NOW() WHERE edb_info_id=? AND data_time=? `
-								sql = fmt.Sprintf(sql, dataTableName)
-								_, err = to.Raw(sql, val, edbInfoId, av).Exec()
-								if err != nil {
-									return err
-								}
-							}
-						}
-						break
-					}
-				} else {
-					nextDateDay := preDate.AddDate(0, 0, 1)
-					nextDateDayStr := nextDateDay.Format(utils.FormatDate)
-
-					preDateDay := preDate.AddDate(0, 0, -1)
-					preDateDayStr := preDateDay.Format(utils.FormatDate)
-
-					for i := 0; i < 35; i++ {
-						if i >= 1 {
-							nextDateDay = nextDateDay.AddDate(0, 0, i)
-							nextDateDayStr = nextDateDay.Format(utils.FormatDate)
-						}
-						if findItem, ok := dataMap[nextDateDayStr]; ok { //上一年同期->下一个月找到
-							timestamp := currentDate.UnixNano() / 1e6
-							timestampStr := fmt.Sprintf("%d", timestamp)
-							val := TbzDiv(currentItem.Value, findItem.Value)
-
-							if existVal, ok := existDataMap[av]; !ok {
-								if _, existOk := existAddDataMap[av]; !existOk {
-									addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
-									isAdd = true
-								}
-								existAddDataMap[av] = av
-							} else {
-								if existVal != val {
-									sql := ` UPDATE %s SET value=?,modify_time=NOW() WHERE edb_info_id=? AND data_time=? `
-									sql = fmt.Sprintf(sql, dataTableName)
-									_, err = to.Raw(sql, val, edbInfoId, av).Exec()
-									if err != nil {
-										return err
-									}
-								}
-							}
-							break
-						} else {
-							if i >= 1 {
-								preDateDay = preDate.AddDate(0, 0, -i)
-								preDateDayStr = nextDateDay.Format(utils.FormatDate)
-							}
-							if findItem, ok := dataMap[preDateDayStr]; ok { //上一年同期->上一个月找到
-								timestamp := currentDate.UnixNano() / 1e6
-								timestampStr := fmt.Sprintf("%d", timestamp)
-								val := TbzDiv(currentItem.Value, findItem.Value)
-
-								if existVal, ok := existDataMap[av]; !ok {
-									if _, existOk := existAddDataMap[av]; !existOk {
-										addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
-										isAdd = true
-									}
-									existAddDataMap[av] = av
-								} else {
-									if existVal != val {
-										sql := ` UPDATE %s SET value=?,modify_time=NOW() WHERE edb_info_id=? AND data_time=? `
-										sql = fmt.Sprintf(sql, dataTableName)
-										_, err = to.Raw(sql, val, edbInfoId, av).Exec()
-										if err != nil {
-											return err
-										}
-									}
-								}
-								break
-							}
-						}
-					}
-				}
-			}
-		}
-	}
-	if isAdd {
-		addSql = strings.TrimRight(addSql, ",")
-		_, err = to.Raw(addSql).Exec()
-		if err != nil {
-			return err
-		}
-	}
-	return
-}

+ 2 - 2
models/data_manage/edb_info_calculate_tcz.go

@@ -89,7 +89,7 @@ func AddCalculateTcz(req *EdbInfoCalculateBatchSaveReq, fromEdbInfo *EdbInfo, ed
 		}
 	} else {
 		edbInfoId = req.EdbInfoId
-		dataTableName := GetEdbDataTableName(utils.DATA_SOURCE_CALCULATE_TCZ)
+		dataTableName := GetEdbDataTableName(utils.DATA_SOURCE_CALCULATE_TCZ, utils.DATA_SUB_SOURCE_EDB)
 		fmt.Println("dataTableName:", dataTableName)
 		deleteSql := ` DELETE FROM %s WHERE edb_info_id=? `
 		deleteSql = fmt.Sprintf(deleteSql, dataTableName)
@@ -112,7 +112,7 @@ func AddCalculateTcz(req *EdbInfoCalculateBatchSaveReq, fromEdbInfo *EdbInfo, ed
 	}
 
 	fmt.Println("EdbInfoId:", req.FromEdbInfoId)
-	dataList, err := GetEdbDataListAll(condition, pars, fromEdbInfo.Source, 0)
+	dataList, err := GetEdbDataListAll(condition, pars, fromEdbInfo.Source, fromEdbInfo.SubSource, 0)
 	if err != nil {
 		return edbInfoId, err
 	}

+ 4 - 4
models/data_manage/edb_info_calculate_zjpj.go

@@ -111,7 +111,7 @@ func EditCalculateZjpj(req *EdbInfoCalculateBatchEditReq, nowEdbInfo, firstEdbIn
 			condition += " AND data_time < ? AND edb_info_id=? "
 			pars = append(pars, req.Formula, firstEdbInfo.EdbInfoId)
 
-			tmpFirstDataList, tmpErr := GetEdbDataListAll(condition, pars, firstEdbInfo.Source, 0)
+			tmpFirstDataList, tmpErr := GetEdbDataListAll(condition, pars, firstEdbInfo.Source, firstEdbInfo.SubSource, 0)
 			if tmpErr != nil {
 				return edbInfoId, tmpErr
 			}
@@ -144,7 +144,7 @@ func EditCalculateZjpj(req *EdbInfoCalculateBatchEditReq, nowEdbInfo, firstEdbIn
 				condition += " AND data_time >= ?  AND data_time < ? AND edb_info_id=? "
 				pars = append(pars, nowFormulaDate, reqFormulaDate, firstEdbInfo.EdbInfoId)
 
-				tmpFirstDataList, tmpErr := GetEdbDataListAll(condition, pars, firstEdbInfo.Source, 0)
+				tmpFirstDataList, tmpErr := GetEdbDataListAll(condition, pars, firstEdbInfo.Source, firstEdbInfo.SubSource, 0)
 				if tmpErr != nil {
 					return edbInfoId, tmpErr
 				}
@@ -197,7 +197,7 @@ func EditCalculateZjpj(req *EdbInfoCalculateBatchEditReq, nowEdbInfo, firstEdbIn
 			//第二个指标的数据列表
 			condition = " AND data_time >= ?  AND edb_info_id=? "
 			pars = append(pars, reqFormulaDate, secondEdbInfo.EdbInfoId)
-			tmpSecondDataList, tmpErr := GetEdbDataListAll(condition, pars, secondEdbInfo.Source, 0)
+			tmpSecondDataList, tmpErr := GetEdbDataListAll(condition, pars, secondEdbInfo.Source, secondEdbInfo.SubSource, 0)
 			if tmpErr != nil {
 				return edbInfoId, tmpErr
 			}
@@ -230,7 +230,7 @@ func EditCalculateZjpj(req *EdbInfoCalculateBatchEditReq, nowEdbInfo, firstEdbIn
 				condition += " AND data_time >= ?  AND data_time < ? AND edb_info_id=? "
 				pars = append(pars, reqFormulaDate, nowFormulaDate, secondEdbInfo.EdbInfoId)
 
-				tmpSecondDataList, tmpErr := GetEdbDataListAll(condition, pars, secondEdbInfo.Source, 0)
+				tmpSecondDataList, tmpErr := GetEdbDataListAll(condition, pars, secondEdbInfo.Source, secondEdbInfo.SubSource, 0)
 				if tmpErr != nil {
 					return edbInfoId, tmpErr
 				}

+ 1 - 0
models/data_manage/edb_source.go

@@ -24,6 +24,7 @@ type EdbSource struct {
 	BridgeFlag       string `description:"桥接服务对象标识"`
 	SourceExtend     string `description:"扩展字段做查询用"`
 	EdbCodeRequired  int    `description:"指标编码是否必填: 0-否; 1-是"`
+	IndexTableName   string `description:"数据源指标表名"`
 }
 
 // GetEdbSourceItemsByCondition 获取指标来源

+ 7 - 0
models/data_manage/response/chart.go

@@ -0,0 +1,7 @@
+package response
+
+// ChartRefreshResp
+// @Description: 图表更新结果
+type ChartRefreshResp struct {
+	RefreshResult bool `description:"刷新结果"`
+}

+ 80 - 0
models/data_stat/edb_info_delete_log.go

@@ -0,0 +1,80 @@
+package data_stat
+
+import (
+	"github.com/beego/beego/v2/client/orm"
+)
+
+// EdbInfoDeleteLog 指标删除日志表
+type EdbInfoDeleteLog struct {
+	Id                 uint64  `orm:"column(id);pk"`
+	EdbInfoId          int     `description:"指标ID"`
+	EdbInfoType        int     `description:"指标类型,0:普通指标,1:预测指标"`
+	SourceName         string  `description:"来源名称"`
+	Source             int     `description:"来源id"`
+	EdbCode            string  `description:"指标编码"`
+	EdbName            string  `description:"指标名称"`
+	EdbNameEn          string  `description:"英文指标名称"`
+	EdbNameSource      string  `description:"指标名称来源"`
+	Frequency          string  `description:"频率"`
+	Unit               string  `description:"单位"`
+	UnitEn             string  `description:"英文单位"`
+	StartDate          string  `description:"起始日期"`
+	EndDate            string  `description:"终止日期"`
+	SysUserId          int     `description:"创建人ID"`
+	SysUserRealName    string  `description:"创建人姓名"`
+	UniqueCode         string  `description:"指标唯一编码"`
+	EdbCreateTime      string  `description:"指标创建时间"`
+	EdbModifyTime      string  `description:"指标修改时间"`
+	CreateTime         string  `description:"创建时间即删除时间"`
+	MinValue           float64 `description:"指标最小值"`
+	MaxValue           float64 `description:"指标最大值"`
+	CalculateFormula   string  `description:"计算公式"`
+	EdbType            int     `description:"指标类型:1:基础指标,2:计算指标"`
+	LatestDate         string  `description:"数据最新日期"`
+	LatestValue        float64 `description:"数据最新值"`
+	MoveType           int     `description:"移动方式:1:领先(默认),2:滞后"`
+	MoveFrequency      string  `description:"移动频度"`
+	NoUpdate           int8    `description:"是否停止更新,0:继续更新;1:停止更新"`
+	ChartImage         string  `description:"图表图片"`
+	Calendar           string  `description:"公历/农历" orm:"default(公历);"`
+	DataDateType       string  `orm:"column(data_date_type);size(255);null;default(交易日)"`
+	ManualSave         int     `description:"是否有手动保存过上下限: 0-否; 1-是"`
+	TerminalCode       string  `description:"终端编码,用于配置在机器上"`
+	DelSysUserId       int     `description:"删除人ID"`
+	DelSysUserRealName string  `description:"删除人姓名"`
+	DataUpdateTime     string  `description:"最近一次数据发生变化的时间"`
+	ErDataUpdateDate   string  `description:"本次更新,数据发生变化的最早日期"`
+}
+
+type EdbInfoDeleteLogItem struct {
+	Id                 uint64  `orm:"column(id);"`
+	EdbInfoId          int     `description:"指标ID"`
+	EdbInfoType        int     `description:"指标类型,0:普通指标,1:预测指标"`
+	SourceName         string  `description:"来源名称"`
+	Source             int     `description:"来源id"`
+	EdbCode            string  `description:"指标编码"`
+	EdbName            string  `description:"指标名称"`
+	EdbNameEn          string  `description:"英文指标名称"`
+	EdbNameSource      string  `description:"指标名称来源"`
+	Frequency          string  `description:"频率"`
+	Unit               string  `description:"单位"`
+	StartDate          string  `description:"起始日期"`
+	EndDate            string  `description:"终止日期"`
+	SysUserId          int     `description:"创建人ID"`
+	SysUserRealName    string  `description:"创建人姓名"`
+	EdbCreateTime      string  `description:"指标创建时间"`
+	CreateTime         string  `description:"创建时间即删除时间"`
+	LatestDate         string  `description:"数据最新日期"`
+	LatestValue        float64 `description:"数据最新值"`
+	TerminalCode       string  `description:"终端编码,用于配置在机器上"`
+	DelSysUserId       int     `description:"删除人ID"`
+	DelSysUserRealName string  `description:"删除人姓名"`
+	DataUpdateTime     string  `description:"最近一次数据发生变化的时间"`
+	ErDataUpdateDate   string  `description:"本次更新,数据发生变化的最早日期"`
+}
+
+func AddEdbDeleteLog(item *EdbInfoDeleteLog) (lastId int64, err error) {
+	o := orm.NewOrmUsingDB("data")
+	lastId, err = o.Insert(item)
+	return
+}

+ 70 - 0
models/data_stat/edb_info_update_log.go

@@ -0,0 +1,70 @@
+package data_stat
+
+import (
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+// EdbInfoUpdateLog 指标更新/刷新日志列表
+type EdbInfoUpdateLog struct {
+	Id                     uint64    `orm:"column(id);pk"`
+	EdbInfoId              int       `description:"指标ID"`
+	SourceName             string    `description:"来源名称"`
+	Source                 int       `description:"来源id"`
+	EdbCode                string    `description:"指标编码"`
+	EdbName                string    `description:"指标名称"`
+	EdbNameSource          string    `description:"指标名称来源"`
+	Frequency              string    `description:"频率"`
+	Unit                   string    `description:"单位"`
+	StartDate              string    `description:"起始日期"`
+	EndDate                string    `description:"终止日期"`
+	SysUserId              int       `description:"创建人ID"`
+	SysUserRealName        string    `description:"创建人姓名"`
+	UniqueCode             string    `description:"指标唯一编码"`
+	EdbCreateTime          time.Time `description:"指标创建时间"`
+	EdbModifyTime          time.Time `description:"指标修改时间"`
+	CreateTime             time.Time `description:"创建时间"`
+	UpdateSysUserId        int       `description:"变更人ID"`
+	UpdateSysUserRealName  string    `description:"变更人姓名"`
+	LatestDate             string    `description:"数据最新日期"`
+	LatestValue            float64   `description:"数据最新值"`
+	TerminalCode           string    `description:"终端编码,用于配置在机器上"`
+	ErDataUpdateDate       string    `description:"本次更新,数据发生变化的最早日期"`
+	UpdateResult           int       `description:"本次刷新操作结果:1成功,2失败"`
+	UpdateFailedReason     string    `description:"刷新失败原因"`
+	DataUpdateResult       int       `description:"数据更新结果:1成功,2失败"`
+	DataUpdateFailedReason string    `description:"数据未正常更新原因"`
+	DataUpdateTime         string    `description:"数据更新时间"`
+	IsSourceRefresh        int       `description:"是否为终端刷新到数据源的刷新操作:0否,1是"`
+}
+
+type EdbInfoUpdateLogItem struct {
+	Id                    uint64 `orm:"column(id);pk"`
+	EdbInfoId             int    `description:"指标ID"`
+	SourceName            string `description:"来源名称"`
+	Source                int    `description:"来源id"`
+	EdbCode               string `description:"指标编码"`
+	EdbName               string `description:"指标名称"`
+	EdbNameSource         string `description:"指标名称来源"`
+	Frequency             string `description:"频率"`
+	Unit                  string `description:"单位"`
+	StartDate             string `description:"起始日期"`
+	EndDate               string `description:"终止日期"`
+	SysUserId             int    `description:"创建人ID"`
+	SysUserRealName       string `description:"创建人姓名"`
+	UpdateSysUserId       int    `description:"变更人ID"`
+	UpdateSysUserRealName string `description:"变更人姓名"`
+	CreateTime            string
+	UniqueCode            string  `description:"指标唯一编码"`
+	LatestDate            string  `description:"数据最新日期"`
+	LatestValue           float64 `description:"数据最新值"`
+	TerminalCode          string  `description:"终端编码,用于配置在机器上"`
+	DataUpdateTime        string  `description:"最近一次数据发生变化的时间"`
+	ErDataUpdateDate      string  `description:"本次更新,数据发生变化的最早日期"`
+}
+
+func AddEdbUpdateLog(item *EdbInfoUpdateLog) (lastId int64, err error) {
+	o := orm.NewOrmUsingDB("data")
+	lastId, err = o.Insert(item)
+	return
+}

+ 12 - 0
models/db.go

@@ -2,6 +2,7 @@ package models
 
 import (
 	"eta/eta_mobile/models/data_manage"
+	"eta/eta_mobile/models/data_stat"
 	"eta/eta_mobile/models/ppt_english"
 	"eta/eta_mobile/models/sandbox"
 	saModel "eta/eta_mobile/models/semantic_analysis"
@@ -108,6 +109,9 @@ func init() {
 
 	// 初始化部分数据表变量(直接init会有顺序问题=_=!)
 	data_manage.InitEdbSource()
+
+	// initDataStat 数据源统计管理相关表
+	initDataStat()
 }
 
 // initSystem 系统表 数据表
@@ -249,3 +253,11 @@ func initBusinessConf() {
 		new(BusinessConfOperationRecord), // 商家配置操作记录表
 	)
 }
+
+// initDataStat 数据源统计管理相关表
+func initDataStat() {
+	orm.RegisterModel(
+		new(data_stat.EdbInfoDeleteLog), // 指标删除日志表
+		new(data_stat.EdbInfoUpdateLog), // 指标更新/刷新日志列表
+	)
+}

+ 1 - 1
models/sandbox/response/sandbox.go

@@ -8,5 +8,5 @@ import (
 // SandboxListResp 沙盘列表返回数据
 type SandboxListResp struct {
 	Paging *paging.PagingItem
-	List   []*sandbox.SandboxListItem
+	List   []*sandbox.Sandbox
 }

+ 31 - 15
models/sandbox/sandbox.go

@@ -6,20 +6,36 @@ import (
 )
 
 // Sandbox 沙盘推演主表
+//type Sandbox struct {
+//	SandboxId           int       `orm:"column(sandbox_id);pk" description:"沙盘id"`
+//	Name                string    `description:"沙盘名称"`
+//	ChartPermissionId   int       `description:"品种id"`
+//	ChartPermissionName string    `description:"品种名称"`
+//	CurrVersion         int       `description:"当前版本"`
+//	Code                string    `description:"沙盘code"`
+//	Content             string    `description:"沙盘数据"`
+//	PicUrl              string    `description:"沙盘图片地址"`
+//	OpUserId            int       `description:"最近一次编辑操作的用户id"`
+//	OpUserName          string    `description:"最近一次编辑的用户名称(冗余字段,避免查表)"`
+//	IsDelete            int8      `description:"是否删除,0:未删除,1:已删除"`
+//	ModifyTime          time.Time `description:"修改时间"`
+//	CreateTime          time.Time `description:"创建时间"`
+//}
+
 type Sandbox struct {
-	SandboxId           int       `orm:"column(sandbox_id);pk" description:"沙盘id"`
-	Name                string    `description:"沙盘名称"`
-	ChartPermissionId   int       `description:"品种id"`
-	ChartPermissionName string    `description:"品种名称"`
-	CurrVersion         int       `description:"当前版本"`
-	Code                string    `description:"沙盘code"`
-	Content             string    `description:"沙盘数据"`
-	PicUrl              string    `description:"沙盘图片地址"`
-	OpUserId            int       `description:"最近一次编辑操作的用户id"`
-	OpUserName          string    `description:"最近一次编辑的用户名称(冗余字段,避免查表)"`
-	IsDelete            int8      `description:"是否删除,0:未删除,1:已删除"`
-	ModifyTime          time.Time `description:"修改时间"`
-	CreateTime          time.Time `description:"创建时间"`
+	SandboxId         int       `orm:"column(sandbox_id);pk" description:"沙盘id"`
+	Name              string    `description:"沙盘名称"`
+	Code              string    `description:"沙盘code"`
+	Content           string    `description:"沙盘数据"`
+	MindmapData       string    `description:"思维导图数据"`
+	PicUrl            string    `description:"沙盘图片地址"`
+	SysUserId         int       `description:"作者id"`
+	SysUserName       string    `description:"作者名称"`
+	IsDelete          int8      `description:"是否删除,0:未删除,1:已删除"`
+	ModifyTime        time.Time `description:"修改时间"`
+	CreateTime        time.Time `description:"创建时间"`
+	SandboxClassifyId int       `description:"分类id"`
+	Sort              int       `description:"排序"`
 }
 
 // Update 沙盘字段变更
@@ -51,9 +67,9 @@ type SandboxListItem struct {
 }
 
 // GetList 获取沙盘列表页
-func GetList(condition string, pars []interface{}, startSize, pageSize int) (total int, list []*SandboxListItem, err error) {
+func GetList(condition string, pars []interface{}, startSize, pageSize int) (total int, list []*Sandbox, err error) {
 	o := orm.NewOrmUsingDB("data")
-	sql := "select a.sandbox_id,a.name,a.chart_permission_id,a.chart_permission_name,a.curr_version,a.code,a.pic_url,a.op_user_id,a.op_user_name,a.modify_time,a.create_time,b.version_code from sandbox as a join sandbox_version b on a.sandbox_id=b.sandbox_id and a.curr_version=b.curr_version where 1=1 AND a.is_delete = 0 "
+	sql := "select a.sandbox_id,a.name,a.code,a.pic_url,a.sys_user_id,a.sys_user_name,a.modify_time,a.create_time from sandbox as a where 1=1 AND a.is_delete = 0 "
 	sql += condition
 	sql += ` order by a.modify_time desc,a.sandbox_id desc`
 

+ 279 - 0
routers/commentsRouter.go

@@ -61,6 +61,258 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/cross_variety:ChartInfoController"] = append(beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/cross_variety:ChartInfoController"],
+        beego.ControllerComments{
+            Method: "Add",
+            Router: `/chart_info/add`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/cross_variety:ChartInfoController"] = append(beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/cross_variety:ChartInfoController"],
+        beego.ControllerComments{
+            Method: "Copy",
+            Router: `/chart_info/copy`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/cross_variety:ChartInfoController"] = append(beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/cross_variety:ChartInfoController"],
+        beego.ControllerComments{
+            Method: "DeleteChartClassify",
+            Router: `/chart_info/delete`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/cross_variety:ChartInfoController"] = append(beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/cross_variety:ChartInfoController"],
+        beego.ControllerComments{
+            Method: "Detail",
+            Router: `/chart_info/detail`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/cross_variety:ChartInfoController"] = append(beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/cross_variety:ChartInfoController"],
+        beego.ControllerComments{
+            Method: "Edit",
+            Router: `/chart_info/edit`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/cross_variety:ChartInfoController"] = append(beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/cross_variety:ChartInfoController"],
+        beego.ControllerComments{
+            Method: "EnInfoEdit",
+            Router: `/chart_info/en/edit`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/cross_variety:ChartInfoController"] = append(beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/cross_variety:ChartInfoController"],
+        beego.ControllerComments{
+            Method: "List",
+            Router: `/chart_info/list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/cross_variety:ChartInfoController"] = append(beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/cross_variety:ChartInfoController"],
+        beego.ControllerComments{
+            Method: "Move",
+            Router: `/chart_info/move`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/cross_variety:ChartInfoController"] = append(beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/cross_variety:ChartInfoController"],
+        beego.ControllerComments{
+            Method: "Preview",
+            Router: `/chart_info/preview`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/cross_variety:ChartInfoController"] = append(beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/cross_variety:ChartInfoController"],
+        beego.ControllerComments{
+            Method: "Refresh",
+            Router: `/chart_info/refresh`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/cross_variety:ChartInfoController"] = append(beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/cross_variety:ChartInfoController"],
+        beego.ControllerComments{
+            Method: "Relation",
+            Router: `/chart_info/relation`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/cross_variety:ChartInfoController"] = append(beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/cross_variety:ChartInfoController"],
+        beego.ControllerComments{
+            Method: "SearchByEs",
+            Router: `/chart_info/search_by_es`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/cross_variety:ClassifyController"] = append(beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/cross_variety:ClassifyController"],
+        beego.ControllerComments{
+            Method: "DeleteChartClassify",
+            Router: `/classify/delete`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/cross_variety:ClassifyController"] = append(beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/cross_variety:ClassifyController"],
+        beego.ControllerComments{
+            Method: "DeleteChartClassifyCheck",
+            Router: `/classify/delete/check`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/cross_variety:ClassifyController"] = append(beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/cross_variety:ClassifyController"],
+        beego.ControllerComments{
+            Method: "EditChartClassify",
+            Router: `/classify/edit`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/cross_variety:ClassifyController"] = append(beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/cross_variety:ClassifyController"],
+        beego.ControllerComments{
+            Method: "List",
+            Router: `/classify/list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/cross_variety:TagController"] = append(beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/cross_variety:TagController"],
+        beego.ControllerComments{
+            Method: "Add",
+            Router: `/tag/add`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/cross_variety:TagController"] = append(beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/cross_variety:TagController"],
+        beego.ControllerComments{
+            Method: "Delete",
+            Router: `/tag/delete`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/cross_variety:TagController"] = append(beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/cross_variety:TagController"],
+        beego.ControllerComments{
+            Method: "DeleteCheck",
+            Router: `/tag/delete/check`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/cross_variety:TagController"] = append(beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/cross_variety:TagController"],
+        beego.ControllerComments{
+            Method: "Edit",
+            Router: `/tag/edit`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/cross_variety:TagController"] = append(beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/cross_variety:TagController"],
+        beego.ControllerComments{
+            Method: "List",
+            Router: `/tag/list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/cross_variety:TagController"] = append(beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/cross_variety:TagController"],
+        beego.ControllerComments{
+            Method: "VarietyEdbList",
+            Router: `/tag/variety_edb/list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/cross_variety:TagController"] = append(beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/cross_variety:TagController"],
+        beego.ControllerComments{
+            Method: "SaveVarietyEdb",
+            Router: `/tag/variety_edb/save`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/cross_variety:VarietyController"] = append(beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/cross_variety:VarietyController"],
+        beego.ControllerComments{
+            Method: "Add",
+            Router: `/variety/add`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/cross_variety:VarietyController"] = append(beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/cross_variety:VarietyController"],
+        beego.ControllerComments{
+            Method: "Delete",
+            Router: `/variety/delete`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/cross_variety:VarietyController"] = append(beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/cross_variety:VarietyController"],
+        beego.ControllerComments{
+            Method: "DeleteCheck",
+            Router: `/variety/delete/check`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/cross_variety:VarietyController"] = append(beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/cross_variety:VarietyController"],
+        beego.ControllerComments{
+            Method: "Edit",
+            Router: `/variety/edit`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/cross_variety:VarietyController"] = append(beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/cross_variety:VarietyController"],
+        beego.ControllerComments{
+            Method: "List",
+            Router: `/variety/list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/future_good:FutureGoodChartClassifyController"] = append(beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/future_good:FutureGoodChartClassifyController"],
         beego.ControllerComments{
             Method: "ChartClassifyList",
@@ -565,6 +817,15 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage:EdbInfoController"] = append(beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage:EdbInfoController"],
+        beego.ControllerComments{
+            Method: "GetBatchChartRefreshResult",
+            Router: `/chart_info/batch_refresh/result`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage:EdbInfoController"] = append(beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage:EdbInfoController"],
         beego.ControllerComments{
             Method: "EdbInfoAdd",
@@ -574,6 +835,15 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage:EdbInfoController"] = append(beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage:EdbInfoController"],
+        beego.ControllerComments{
+            Method: "EdbInfoBatchAdd",
+            Router: `/edb_info/batch/add`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage:EdbInfoController"] = append(beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage:EdbInfoController"],
         beego.ControllerComments{
             Method: "EdbChartList",
@@ -619,6 +889,15 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage:EdbInfoController"] = append(beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage:EdbInfoController"],
+        beego.ControllerComments{
+            Method: "EdbInfoExistCheck",
+            Router: `/edb_info/exist/check`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage:EdbInfoController"] = append(beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage:EdbInfoController"],
         beego.ControllerComments{
             Method: "EdbInfoFilterByEs",

+ 9 - 0
routers/router.go

@@ -11,6 +11,7 @@ import (
 	"eta/eta_mobile/controllers"
 	"eta/eta_mobile/controllers/data_manage"
 	"eta/eta_mobile/controllers/data_manage/correlation"
+	"eta/eta_mobile/controllers/data_manage/cross_variety"
 	"eta/eta_mobile/controllers/data_manage/future_good"
 	"eta/eta_mobile/controllers/data_manage/line_equation"
 	"eta/eta_mobile/controllers/data_manage/line_feature"
@@ -176,6 +177,14 @@ func init() {
 				&english_report.EnglishCompanyController{},
 			),
 		),
+		web.NSNamespace("/cross_variety", //跨品种分析
+			web.NSInclude(
+				&cross_variety.ClassifyController{},
+				&cross_variety.ChartInfoController{},
+				&cross_variety.VarietyController{},
+				&cross_variety.TagController{},
+			),
+		),
 	)
 	web.AddNamespace(ns)
 }

+ 30 - 0
services/data/base_edb_lib.go

@@ -301,3 +301,33 @@ func HttpPost(url, postData string, params ...string) ([]byte, error) {
 	fmt.Println("HttpPost:" + string(b))
 	return b, err
 }
+
+// AddEdbData 新增指标数据
+func AddEdbDataWindWsd(source int, stockCode, edbCode string) (resp *models.BaseResponse, err error) {
+	param := make(map[string]interface{})
+	param["EdbCode"] = edbCode
+	param["StockCode"] = stockCode
+	param["Source"] = source
+	urlStr := `wind/wsd/add`
+	if urlStr == "" {
+		err = fmt.Errorf("未实现该指标的刷新接口,请联系管理员")
+		return
+	}
+	resp, err = postRefreshEdbData(param, urlStr)
+	return
+}
+
+// AddEdbDataThsDs 新增指标数据
+func AddEdbDataThsDs(source int, stockCode, edbCode string) (resp *models.BaseResponse, err error) {
+	param := make(map[string]interface{})
+	param["EdbCode"] = edbCode
+	param["StockCode"] = stockCode
+	param["Source"] = source
+	urlStr := `ths/ds/add`
+	if urlStr == "" {
+		err = fmt.Errorf("未实现该指标的刷新接口,请联系管理员")
+		return
+	}
+	resp, err = postRefreshEdbData(param, urlStr)
+	return
+}

+ 47 - 0
services/data/chart_classify.go

@@ -34,3 +34,50 @@ func ChartClassifyItemsMakeTree(allNode []*data_manage.ChartClassifyItems, node
 		node.Children = childrenArr
 	}
 }
+
+// HandleNoPermissionChart 图表列表返回,将没有权限的图表移除
+func HandleNoPermissionChart(allNodes []*data_manage.ChartClassifyItems, noPermissionChartIdMap map[int]bool) (newAllNodes []*data_manage.ChartClassifyItems) {
+	// 移除没有权限的图表
+	newAllNodes = make([]*data_manage.ChartClassifyItems, 0)
+	for _, node := range allNodes {
+		// 二级分类
+		tmpNodeInfo := *node
+		tmpNodeList := make([]*data_manage.ChartClassifyItems, 0)
+		if node.Children != nil {
+			for _, chartList := range node.Children {
+				tmpInfo := *chartList
+				tmpList := make([]*data_manage.ChartClassifyItems, 0)
+
+				if chartList.Children != nil {
+					for _, chartInfo := range chartList.Children {
+						thirdInfo := *chartInfo
+						thirdList := make([]*data_manage.ChartClassifyItems, 0)
+						// 如果指标不可见,那么就不返回该指标
+						if _, ok := noPermissionChartIdMap[chartInfo.ChartInfoId]; ok {
+							continue
+						}
+						tmpList = append(tmpList, chartInfo)
+
+						if chartInfo.Children != nil {
+							for _, thirdChart := range chartInfo.Children {
+								// 如果指标不可见,那么就不返回该指标
+								if _, ok := noPermissionChartIdMap[chartInfo.ChartInfoId]; ok {
+									continue
+								}
+								thirdList = append(thirdList, thirdChart)
+							}
+						}
+						thirdInfo.Children = thirdList
+						tmpList = append(tmpList, &thirdInfo)
+					}
+				}
+				tmpInfo.Children = tmpList
+				tmpNodeList = append(tmpNodeList, &tmpInfo)
+			}
+		}
+		tmpNodeInfo.Children = tmpNodeList
+		newAllNodes = append(newAllNodes, &tmpNodeInfo)
+	}
+
+	return
+}

+ 118 - 16
services/data/chart_info.go

@@ -273,7 +273,7 @@ func getEdbDataMapList(chartInfoId, chartType int, calendar, startDate, endDate
 		//var newEdbInfo *data_manage.EdbInfo
 		switch v.EdbInfoCategoryType {
 		case 0:
-			dataList, err = data_manage.GetEdbDataList(v.Source, v.EdbInfoId, startDateReal, endDate)
+			dataList, err = data_manage.GetEdbDataList(v.Source, v.SubSource, v.EdbInfoId, startDateReal, endDate)
 		case 1:
 			_, dataList, _, _, err, _ = GetPredictDataListByPredictEdbInfoId(v.EdbInfoId, startDateReal, endDate, false)
 		default:
@@ -572,6 +572,7 @@ func GetSeasonEdbInfoDataListByXDateNong(result *data_manage.EdbDataResult, late
 	itemLength := len(result.List[length-1].Items)
 	//获取数据的最新日期
 	lastDate := result.List[length-1].Items[itemLength-1].DataTime
+	maxY := result.List[length-1].Year
 	lastDateT, tmpErr := time.Parse(utils.FormatDate, lastDate)
 	if tmpErr != nil {
 		err = tmpErr
@@ -586,6 +587,7 @@ func GetSeasonEdbInfoDataListByXDateNong(result *data_manage.EdbDataResult, late
 	quarterMap := make(map[string][]*data_manage.EdbDataList, 0)
 
 	//整理出日期
+	var startTmpT, endTmpT time.Time
 	idx := 1
 	chartLegendMap := make(map[string]int, 0)
 	for currentStartYear := startYear; currentStartYear <= endYear; currentStartYear++ {
@@ -624,6 +626,8 @@ func GetSeasonEdbInfoDataListByXDateNong(result *data_manage.EdbDataResult, late
 		}
 		dataMap[showName] = item
 		fmt.Println("年份" + showName + "日期" + startStr + " " + endStr)
+		startTmpT = startT
+		endTmpT = endT
 		chartLegendMap[showName] = idx
 		idx++
 		if lastDateT.Before(endT) {
@@ -646,7 +650,7 @@ func GetSeasonEdbInfoDataListByXDateNong(result *data_manage.EdbDataResult, late
 	}
 
 	//判断哪些点应该落在同一条时间线上
-	maxY := lastDateT.Year()
+	/*maxY := lastDateT.Year()
 	changeFlag := false
 	if lastDateT.Month() >= 11 {
 		maxY = maxY + 1
@@ -654,22 +658,28 @@ func GetSeasonEdbInfoDataListByXDateNong(result *data_manage.EdbDataResult, late
 	if maxY < nowYear {
 		changeFlag = true
 		maxY = nowYear
-	}
-	endTmp := fmt.Sprintf("%d-%s", maxY, xEndDate)
+	}*/
+	/*endTmp := fmt.Sprintf("%d-%s", maxY, xEndDate)
 	endTmpT, _ := time.Parse(utils.FormatDate, endTmp)
 	minY := maxY
 	if jumpYear == 1 {
 		minY = maxY - 1
 	}
 	startTmp := fmt.Sprintf("%d-%s", minY, xStartDate)
-	startTmpT, _ := time.Parse(utils.FormatDate, startTmp)
+	startTmpT, _ := time.Parse(utils.FormatDate, startTmp)*/
 
 	fmt.Println("横轴截取日" + startTmpT.Format(utils.FormatDate) + " " + endTmpT.Format(utils.FormatDate))
+	fmt.Printf("lastDateT.Year() 为%d \n", lastDateT.Year())
+	fmt.Printf("maxY 为%d \n", maxY)
 	for name, dateItem := range dataMap {
-		lv, ok1 := yearDataListMap[dateItem.EndDate.Year()]
-		if changeFlag {
-			lv, ok1 = yearDataListMap[dateItem.StartDate.Year()]
+		tY := dateItem.EndDate.Year()
+		if lastDateT.Month() >= 11 {
+			if maxY > endTmpT.Year() {
+				tY = tY + 1
+			}
 		}
+		lv, ok1 := yearDataListMap[tY]
+		fmt.Printf("name %s yearDataListMap[%d]\n", name, tY)
 		if !ok1 {
 			continue
 		}
@@ -1388,7 +1398,7 @@ func ChartInfoRefreshV2(chartInfoId int) (err error) {
 // @author Roc
 // @datetime 2022-09-16 10:15:38
 // @description 将原来自己写的一套获取所有关联指标,然后刷新指标逻辑 改成  只获取使用的指标id,然后遍历去调用“指标刷新服务”
-func BatchChartInfoRefreshV2(chartInfoList []*data_manage.ChartInfo) (err error) {
+func BatchChartInfoRefreshV2(chartInfoList []*data_manage.ChartInfo, redisKey string) (err error, isAsync bool) {
 	if len(chartInfoList) <= 0 {
 		return
 	}
@@ -1397,15 +1407,28 @@ func BatchChartInfoRefreshV2(chartInfoList []*data_manage.ChartInfo) (err error)
 		chartInfoIdSlice = append(chartInfoIdSlice, chartInfo.ChartInfoId)
 	}
 
-	var errmsg string
+	var errMsg string
 	defer func() {
 		if err != nil {
-			go alarm_msg.SendAlarmMsg("ChartInfoRefresh:"+errmsg, 3)
+			go alarm_msg.SendAlarmMsg("ChartInfoRefresh:"+errMsg, 3)
 			//go utils.SendEmail(utils.APPNAME+"【"+utils.RunMode+"】"+"失败提醒", "ChartInfoRefresh:"+errmsg, utils.EmailSendToUsers)
-			fmt.Println("ChartInfoRefresh Err:" + errmsg)
+			fmt.Println("ChartInfoRefresh Err:" + errMsg)
 		}
 	}()
 
+	// 是否删除缓存
+	isDeleteCache := true
+	if redisKey != `` {
+		//设置最多10分钟缓存
+		utils.Rc.SetNX(redisKey, 1, time.Minute*10)
+		defer func() {
+			if isDeleteCache {
+				utils.Rc.Delete(redisKey)
+			}
+		}()
+	}
+
+	// 获取需要刷新的指标信息
 	edbIdList := make([]int, 0)
 	edbInfoIdMap := make(map[int]int)
 	edbMappingList, err := data_manage.GetChartEdbMappingListByIdList(chartInfoIdSlice)
@@ -1416,10 +1439,89 @@ func BatchChartInfoRefreshV2(chartInfoList []*data_manage.ChartInfo) (err error)
 		}
 	}
 
-	// 批量刷新
-	err, _ = EdbInfoRefreshAllFromBaseV3(edbIdList, false, true)
-	if err != nil {
-		return
+	// 获取需要刷新的指标列表
+	newBaseEdbInfoArr, newBasePredictEdbInfoArr, newCalculateMap, newPredictCalculateMap, calculateArr, predictCalculateArr := getEdbInfoIdList(edbIdList)
+
+	// 需要刷新的指标数量
+	totalEdbInfo := len(newBaseEdbInfoArr) + len(calculateArr) + len(predictCalculateArr)
+
+	if totalEdbInfo > 20 { // 关联指标过多的时候,异步刷新
+		isAsync = true
+		isDeleteCache = false // 不删除缓存
+		go refreshChartEdbInfo(chartInfoList, redisKey, newBaseEdbInfoArr, newBasePredictEdbInfoArr, newCalculateMap, newPredictCalculateMap, calculateArr, predictCalculateArr)
+	} else {
+		err = edbInfoRefreshAll(false, newBaseEdbInfoArr, newBasePredictEdbInfoArr, newCalculateMap, newPredictCalculateMap, calculateArr, predictCalculateArr)
+
+		//清除图表缓存
+		for _, v := range chartInfoList {
+			key := utils.HZ_CHART_LIB_DETAIL + v.UniqueCode
+			_ = utils.Rc.Delete(key)
+		}
+	}
+
+	return
+}
+
+// refreshChartEdbInfo
+// @Description: 刷新图表中的质保列表
+// @author: Roc
+// @datetime 2023-12-01 16:05:39
+// @param chartInfoList []*data_manage.ChartInfo
+// @param redisKey string
+// @param newBaseEdbInfoArr []*data_manage.EdbInfo
+// @param newBasePredictEdbInfoArr []*data_manage.EdbInfo
+// @param newCalculateMap map[int]*data_manage.EdbInfo
+// @param newPredictCalculateMap map[int]*data_manage.EdbInfo
+// @param calculateArr []int
+// @param predictCalculateArr []int
+func refreshChartEdbInfo(chartInfoList []*data_manage.ChartInfo, redisKey string, newBaseEdbInfoArr, newBasePredictEdbInfoArr []*data_manage.EdbInfo, newCalculateMap, newPredictCalculateMap map[int]*data_manage.EdbInfo, calculateArr, predictCalculateArr []int) {
+	edbInfoRefreshAll(false, newBaseEdbInfoArr, newBasePredictEdbInfoArr, newCalculateMap, newPredictCalculateMap, calculateArr, predictCalculateArr)
+
+	//清除图表缓存
+	for _, v := range chartInfoList {
+		key := utils.HZ_CHART_LIB_DETAIL + v.UniqueCode
+		_ = utils.Rc.Delete(key)
+	}
+	// 如果是有插入redisKey,那么刷新结束后就清除缓存
+	if redisKey != `` {
+		utils.Rc.Delete(redisKey)
+	}
+}
+
+// GetBatchChartRefreshKey
+// @Description: 获取批量刷新key
+// @author: Roc
+// @datetime 2023-11-30 13:30:26
+// @param source string
+// @param reportId int
+// @param reportChapterId int
+// @return string
+func GetBatchChartRefreshKey(source string, reportId, reportChapterId int) string {
+	if source == `` {
+		return ``
+	}
+
+	return fmt.Sprint("batch_chart_refresh:", source, ":", reportId, ":", reportChapterId)
+}
+
+// CheckBatchChartRefreshResult
+// @Description: 判断报告中的图表是否刷新完成
+// @author: Roc
+// @datetime 2023-11-30 13:30:26
+// @param source string
+// @param reportId int
+// @param reportChapterId int
+// @return string
+func CheckBatchChartRefreshResult(source string, reportId, reportChapterId int) (refreshResult bool) {
+	refreshResult = true
+	redisKey := GetBatchChartRefreshKey(source, reportId, reportChapterId)
+	if redisKey != `` {
+		// 如果找到了key,那么就是还在更新中
+		isOk := utils.Rc.IsExist(redisKey)
+		if isOk {
+			refreshResult = false
+		}
 	}
+
 	return
 }

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

@@ -256,7 +256,7 @@ func GetChartDataByEdbInfo(edbInfoMappingA, edbInfoMappingB *data_manage.ChartEd
 	aDataList := make([]*data_manage.EdbDataList, 0)
 	switch baseEdbInfo.EdbInfoCategoryType {
 	case 0:
-		aDataList, err = data_manage.GetEdbDataList(baseEdbInfo.Source, baseEdbInfo.EdbInfoId, startDate, endDate)
+		aDataList, err = data_manage.GetEdbDataList(baseEdbInfo.Source, baseEdbInfo.SubSource, baseEdbInfo.EdbInfoId, startDate, endDate)
 	case 1:
 		_, aDataList, _, _, err, _ = data.GetPredictDataListByPredictEdbInfoId(baseEdbInfo.EdbInfoId, startDate, endDate, false)
 	default:
@@ -268,7 +268,7 @@ func GetChartDataByEdbInfo(edbInfoMappingA, edbInfoMappingB *data_manage.ChartEd
 	bDataList := make([]*data_manage.EdbDataList, 0)
 	switch changeEdbInfo.EdbInfoCategoryType {
 	case 0:
-		bDataList, err = data_manage.GetEdbDataList(changeEdbInfo.Source, changeEdbInfo.EdbInfoId, "", "")
+		bDataList, err = data_manage.GetEdbDataList(changeEdbInfo.Source, changeEdbInfo.SubSource, changeEdbInfo.EdbInfoId, "", "")
 	case 1:
 		_, bDataList, _, _, err, _ = data.GetPredictDataListByPredictEdbInfoId(changeEdbInfo.EdbInfoId, "", "", false)
 	default:
@@ -459,7 +459,7 @@ func GetRollingCorrelationChartDataByEdbInfo(edbInfoMappingA, edbInfoMappingB *d
 	aDataList := make([]*data_manage.EdbDataList, 0)
 	switch baseEdbInfo.EdbInfoCategoryType {
 	case 0:
-		aDataList, err = data_manage.GetEdbDataList(baseEdbInfo.Source, baseEdbInfo.EdbInfoId, startDate, endDate)
+		aDataList, err = data_manage.GetEdbDataList(baseEdbInfo.Source, baseEdbInfo.SubSource, baseEdbInfo.EdbInfoId, startDate, endDate)
 	case 1:
 		_, aDataList, _, _, err, _ = data.GetPredictDataListByPredictEdbInfoId(baseEdbInfo.EdbInfoId, startDate, endDate, true)
 	default:
@@ -471,7 +471,7 @@ func GetRollingCorrelationChartDataByEdbInfo(edbInfoMappingA, edbInfoMappingB *d
 	bDataList := make([]*data_manage.EdbDataList, 0)
 	switch changeEdbInfo.EdbInfoCategoryType {
 	case 0:
-		bDataList, err = data_manage.GetEdbDataList(changeEdbInfo.Source, changeEdbInfo.EdbInfoId, "", "")
+		bDataList, err = data_manage.GetEdbDataList(changeEdbInfo.Source, changeEdbInfo.SubSource, changeEdbInfo.EdbInfoId, "", "")
 	case 1:
 		_, bDataList, _, _, err, _ = data.GetPredictDataListByPredictEdbInfoId(changeEdbInfo.EdbInfoId, "", "", false)
 	default:

+ 809 - 0
services/data/cross_variety/chart.go

@@ -0,0 +1,809 @@
+package cross_variety
+
+import (
+	"encoding/json"
+	"errors"
+	"eta/eta_mobile/models/data_manage"
+	cross_varietyModel "eta/eta_mobile/models/data_manage/cross_variety"
+	"eta/eta_mobile/models/data_manage/cross_variety/request"
+	"eta/eta_mobile/models/system"
+	"eta/eta_mobile/services/data"
+	"eta/eta_mobile/utils"
+	"fmt"
+	"github.com/shopspring/decimal"
+	"strconv"
+	"strings"
+	"time"
+)
+
+// ChartInfoResp 截面散点图数据
+type ChartInfoResp struct {
+	XName       string                         `description:"x轴名称"`
+	XNameEn     string                         `description:"x轴名称(英文)"`
+	XUnitName   string                         `description:"x轴单位名称"`
+	XUnitNameEn string                         `description:"x轴单位名称(英文)"`
+	YName       string                         `description:"y轴名称"`
+	YNameEn     string                         `description:"y轴名称(英文)"`
+	YUnitName   string                         `description:"y轴单位名称"`
+	YUnitNameEn string                         `description:"y轴单位名称(英文)"`
+	XMinValue   string                         `description:"X轴的最小值"`
+	XMaxValue   string                         `description:"X轴的最大值"`
+	YMinValue   string                         `description:"Y轴的最小值"`
+	YMaxValue   string                         `description:"Y轴的最大值"`
+	DataList    []SectionScatterSeriesItemResp `description:"数据列"`
+}
+
+// SectionScatterSeriesItemResp 系列的返回
+type SectionScatterSeriesItemResp struct {
+	Name                string            `description:"系列名"`
+	NameEn              string            `description:"系列名(英文)"`
+	Color               string            `description:"颜色"`
+	CoordinatePointData []CoordinatePoint `description:"趋势线的前后坐标点"`
+}
+
+// SectionScatterEdbItemResp 截面散点的返回参数
+type SectionScatterEdbItemResp struct {
+	XEdbInfoId int     `description:"X轴指标id"`
+	XDate      string  `description:"X轴指标实际日期"`
+	XName      string  `description:"X轴指标名称"`
+	XNameEn    string  `description:"X轴指标英文名称"`
+	XValue     float64 `description:"X轴实际值"`
+	YEdbInfoId int     `description:"Y轴指标id"`
+	YDate      string  `description:"Y轴指标实际日期"`
+	YName      string  `description:"Y轴指标名称"`
+	YNameEn    string  `description:"Y轴指标英文名称"`
+	YValue     float64 `description:"Y轴实际值"`
+	IsShow     bool    `description:"是否展示"`
+	Name       string  `description:"标签名称"`
+	NameEn     string  `description:"英文标签名称"`
+}
+
+// CoordinatePoint 坐标点
+type CoordinatePoint struct {
+	X          float64
+	Y          float64
+	XEdbInfoId int
+	YEdbInfoId int
+	XDate      string
+	YDate      string
+}
+
+// GetChartData
+// @Description: 获取跨品种分析图表数据
+// @author: Roc
+// @datetime 2023-11-24 09:42:59
+// @param chartInfoId int
+// @param config request.ChartConfigReq
+// @return edbList []*data_manage.ChartEdbInfoMapping
+// @return dataResp ChartInfoResp
+// @return err error
+// @return errMsg string
+// @return isSendEmail bool
+func GetChartData(chartInfoId int, config request.ChartConfigReq) (edbList []*data_manage.ChartEdbInfoMapping, dataResp ChartInfoResp, err error, errMsg string, isSendEmail bool) {
+	moveUnitDays, ok := utils.FrequencyDaysMap[config.CalculateUnit]
+	if !ok {
+		errMsg = "错误的分析周期"
+		err = errors.New(errMsg)
+		isSendEmail = false
+		return
+	}
+
+	isSendEmail = true
+
+	// 品种map
+	varietyMap := make(map[int]*cross_varietyModel.ChartVariety)
+	{
+		varietyList, tmpErr := cross_varietyModel.GetVarietyListByIdList(config.VarietyList)
+		if tmpErr != nil {
+			err = tmpErr
+			return
+		}
+		for _, v := range varietyList {
+			varietyMap[v.ChartVarietyId] = v
+		}
+	}
+
+	// 标签m
+	var xTagInfo, yTagInfo *cross_varietyModel.ChartTag
+	{
+		tagList, tmpErr := cross_varietyModel.GetTagListByIdList([]int{config.TagX, config.TagY})
+		if tmpErr != nil {
+			err = tmpErr
+			return
+		}
+		for _, v := range tagList {
+			if v.ChartTagId == config.TagX {
+				xTagInfo = v
+			} else if v.ChartTagId == config.TagY {
+				yTagInfo = v
+			}
+		}
+	}
+	if xTagInfo == nil {
+		errMsg = "找不到对应的X轴标签"
+		err = errors.New(errMsg)
+		return
+	}
+	if yTagInfo == nil {
+		errMsg = "找不到对应的Y轴标签"
+		err = errors.New(errMsg)
+		return
+	}
+
+	xVarietyEdbMap, yVarietyEdbMap, edbInfoIdList, err := GetXYEdbIdList(config.TagX, config.TagY, config.VarietyList)
+	if err != nil {
+		return
+	}
+
+	if len(edbInfoIdList) <= 0 {
+		errMsg = "品种未配置指标"
+		err = errors.New(errMsg)
+		isSendEmail = false
+		return
+	}
+	mappingList, err := data_manage.GetChartEdbMappingListByEdbInfoIdList(edbInfoIdList)
+	if err != nil {
+		errMsg = "获取指标信息失败"
+		err = errors.New("获取指标信息失败,ERR:" + err.Error())
+		return
+	}
+
+	// 指标对应的所有数据
+	chartType := 1 //1:普通图,2:季节性图
+	calendar := "公历"
+	edbDataListMap, edbList, err := data.GetEdbDataMapList(chartInfoId, chartType, calendar, "", "", mappingList, "")
+	if err != nil {
+		return
+	}
+
+	currDay := time.Now()
+	currDay = time.Date(currDay.Year(), currDay.Month(), currDay.Day(), 0, 0, 0, 0, time.Local)
+
+	dataMap := make(map[string]float64)
+	dateMap := make(map[string]string)
+	for dateIndex, dateConfig := range config.DateConfigList {
+		for _, edbInfoMapping := range mappingList {
+			// 数据会是正序的
+			dataList, ok := edbDataListMap[edbInfoMapping.EdbInfoId]
+			if !ok {
+				continue
+			}
+
+			lenData := len(dataList)
+			if lenData <= 0 {
+				continue
+			}
+
+			// 数据开始日期
+			endDateStr := ``
+			var endDate time.Time
+			// 数据的开始索引
+			k := lenData - 1
+			var currVal float64
+			switch dateConfig.DateType {
+			case 1: // 1:最新日期;
+				endDateStr = dataList[k].DataTime
+				tmpDate, tmpErr := time.ParseInLocation(utils.FormatDate, endDateStr, time.Local)
+				if tmpErr != nil {
+					err = tmpErr
+					return
+				}
+				endDate = tmpDate
+				currVal = dataList[k].Value
+			case 2: // 2:N天前
+				tmpEndDate := currDay.AddDate(0, 0, -dateConfig.Num)
+				tmpEndDateStr := tmpEndDate.Format(utils.FormatDate)
+
+				for i := k; i >= 0; i-- {
+					tmpDateStr := dataList[i].DataTime
+					// 如果正好是这一天,那么就直接break了
+					if tmpEndDateStr == tmpDateStr {
+						k = i
+						endDateStr = tmpDateStr
+						currVal = dataList[i].Value
+						break
+					}
+					tmpDate, tmpErr := time.ParseInLocation(utils.FormatDate, tmpDateStr, time.Local)
+					if tmpErr != nil {
+						err = tmpErr
+						return
+					}
+					// 如果这期的日期晚于选择的日期,那么继续遍历
+					if tmpDate.After(tmpEndDate) {
+						continue
+					}
+					k = i
+					endDateStr = tmpDateStr
+					endDate = tmpDate
+					currVal = dataList[i].Value
+					break
+				}
+			}
+
+			// 没有找到日期,那么就不处理
+			if endDateStr == `` || endDate.IsZero() {
+				continue
+			}
+
+			// 最早的日期
+			earliestDate := endDate.AddDate(0, 0, -config.CalculateValue*moveUnitDays)
+			earliestDateStr := earliestDate.Format(utils.FormatDate)
+
+			var minVal, maxVal float64
+			var isNotFirst bool // 是否是第一条数据
+			for i := k; i >= 0; i-- {
+				tmpData := dataList[i]
+				if !isNotFirst {
+					maxVal = tmpData.Value
+					minVal = tmpData.Value
+					isNotFirst = true
+					continue
+				}
+
+				tmpDateStr := dataList[i].DataTime
+				// 如果正好是这一天,那么就直接break了
+				if earliestDateStr == tmpDateStr {
+					break
+				}
+				tmpDate, tmpErr := time.ParseInLocation(utils.FormatDate, tmpDateStr, time.Local)
+				if tmpErr != nil {
+					err = tmpErr
+					return
+				}
+				// 如果这期的日期早于选择的日期,那么继续停止遍历
+				if tmpDate.Before(earliestDate) {
+					continue
+				}
+
+				if tmpData.Value > maxVal {
+					maxVal = tmpData.Value
+				}
+				if tmpData.Value < minVal {
+					minVal = tmpData.Value
+				}
+			}
+
+			// 最大值等于最小值,说明计算结果无效
+			if maxVal == minVal {
+				continue
+			}
+			//百分位=(现值-Min)/(Max-Min)
+			tmpV := (currVal - minVal) / (maxVal - minVal) * 100
+			tmpV, _ = decimal.NewFromFloat(tmpV).Round(4).Float64()
+
+			// key的生成(日期配置下标+指标id)
+			key := fmt.Sprint(dateIndex, "_", edbInfoMapping.EdbInfoId)
+			dataMap[key] = tmpV
+			dateMap[key] = endDateStr
+		}
+	}
+
+	// 返回数据处理
+	dataList := make([]SectionScatterSeriesItemResp, 0)
+	var xMinVal, xMaxVal, yMinVal, yMaxVal float64
+	var isNotFirst bool
+
+	for _, varietyId := range config.VarietyList {
+		xEdbInfoId, ok1 := xVarietyEdbMap[varietyId]
+		if !ok1 {
+			continue
+		}
+		yEdbInfoId, ok2 := yVarietyEdbMap[varietyId]
+		if !ok2 {
+			continue
+		}
+		variety, ok := varietyMap[varietyId]
+		if !ok {
+			continue
+		}
+
+		coordinatePointList := make([]CoordinatePoint, 0)
+
+		for dateIndex, _ := range config.DateConfigList {
+			key1 := fmt.Sprint(dateIndex, "_", xEdbInfoId)
+			xVal, ok1 := dataMap[key1]
+			if !ok1 {
+				continue
+			}
+			key2 := fmt.Sprint(dateIndex, "_", yEdbInfoId)
+			yVal, ok2 := dataMap[key2]
+			if !ok2 {
+				continue
+			}
+			if !isNotFirst {
+				xMinVal = xVal
+				xMaxVal = xVal
+				yMinVal = yVal
+				yMaxVal = yVal
+				isNotFirst = true
+			} else {
+				if xVal < xMinVal {
+					xMinVal = xVal
+				}
+				if xVal > xMaxVal {
+					xMaxVal = xVal
+				}
+				if yVal < yMinVal {
+					yMinVal = yVal
+				}
+				if yVal > yMaxVal {
+					yMaxVal = yVal
+				}
+			}
+			coordinatePointList = append(coordinatePointList, CoordinatePoint{
+				X:          xVal,
+				Y:          yVal,
+				XEdbInfoId: xEdbInfoId,
+				YEdbInfoId: yEdbInfoId,
+				XDate:      dateMap[key1],
+				YDate:      dateMap[key2],
+			})
+		}
+
+		dataList = append(dataList, SectionScatterSeriesItemResp{
+			Name:                variety.ChartVarietyName,
+			NameEn:              variety.ChartVarietyNameEn,
+			Color:               "",
+			CoordinatePointData: coordinatePointList,
+		})
+	}
+
+	dataResp = ChartInfoResp{
+		XName:       xTagInfo.ChartTagName + "百分位",
+		XNameEn:     xTagInfo.ChartTagNameEn,
+		XUnitName:   "%",
+		XUnitNameEn: "%",
+		YName:       yTagInfo.ChartTagName + "百分位",
+		YNameEn:     yTagInfo.ChartTagNameEn,
+		YUnitName:   "%",
+		YUnitNameEn: "%",
+		XMinValue:   fmt.Sprint(xMinVal),
+		XMaxValue:   fmt.Sprint(xMaxVal),
+		YMinValue:   fmt.Sprint(yMinVal),
+		YMaxValue:   fmt.Sprint(yMaxVal),
+		DataList:    dataList,
+	}
+
+	// 去除返回指标中的数据信息,避免没必要的数据传输
+	for k, _ := range edbList {
+		edbList[k].DataList = nil
+	}
+
+	return
+}
+
+// CheckIsEnChart
+// @Description: 检测是否展示英文名称
+// @author: Roc
+// @datetime 2023-11-28 20:54:41
+// @param chartNameEn string
+// @param dataResp ChartInfoResp
+// @return bool
+func CheckIsEnChart(chartNameEn string, dataResp ChartInfoResp) bool {
+	if chartNameEn == "" {
+		return false
+	}
+
+	if dataResp.XNameEn == `` {
+		return false
+	}
+	if dataResp.YNameEn == `` {
+		return false
+	}
+	for _, v := range dataResp.DataList {
+		if v.NameEn == `` {
+			return false
+		}
+	}
+	return true
+}
+
+// GetXYEdbIdList
+// @Description: 根据标签id和品种获取指标列表信息
+// @author: Roc
+// @datetime 2023-11-27 14:31:23
+// @param tagX int
+// @param tagY int
+// @param varietyList []int
+// @return xVarietyEdbMap map[int]int
+// @return yVarietyEdbMap map[int]int
+// @return edbInfoIdList []int
+// @return errMsg string
+// @return err error
+func GetXYEdbIdList(tagX, tagY int, varietyList []int) (xVarietyEdbMap, yVarietyEdbMap map[int]int, edbInfoIdList []int, err error) {
+	edbInfoIdList = make([]int, 0)
+	xVarietyEdbMap = make(map[int]int)
+	yVarietyEdbMap = make(map[int]int)
+	xList, err := cross_varietyModel.GetChartTagVarietyListByTagAndVariety(tagX, varietyList)
+	if err != nil {
+		err = errors.New("获取X轴的品种指标配置信息失败,Err:" + err.Error())
+		return
+	}
+	yList, err := cross_varietyModel.GetChartTagVarietyListByTagAndVariety(tagY, varietyList)
+	if err != nil {
+		err = errors.New("获取Y轴的品种指标配置信息失败,Err:" + err.Error())
+		return
+	}
+
+	baseVarietyIdMap := make(map[int]int)
+	for _, v := range xList {
+		baseVarietyIdMap[v.ChartVarietyId] = v.ChartVarietyId
+	}
+
+	// 两个标签里面的品种并集
+	needVarietyIdMap := make(map[int]int)
+	for _, v := range yList {
+		if val, ok := baseVarietyIdMap[v.ChartVarietyId]; ok {
+			// 如果在 map2 中存在相同的键,则将键和值添加到结果中
+			needVarietyIdMap[v.ChartVarietyId] = val
+		}
+	}
+
+	for _, v := range xList {
+		if _, ok := needVarietyIdMap[v.ChartVarietyId]; ok {
+			xVarietyEdbMap[v.ChartVarietyId] = v.EdbInfoId
+			edbInfoIdList = append(edbInfoIdList, v.EdbInfoId)
+		}
+	}
+	for _, v := range yList {
+		if _, ok := needVarietyIdMap[v.ChartVarietyId]; ok {
+			yVarietyEdbMap[v.ChartVarietyId] = v.EdbInfoId
+			edbInfoIdList = append(edbInfoIdList, v.EdbInfoId)
+		}
+	}
+
+	return
+}
+
+// AddChartInfo
+// @Description: AddChartInfo
+// @author: Roc
+// @datetime 2023-11-24 15:58:14
+// @param req request.AddChartReq
+// @param sysUser *system.Admin
+// @return chartInfo *data_manage.ChartInfo
+// @return err error
+// @return errMsg string
+// @return isSendEmail bool
+func AddChartInfo(req request.AddChartReq, sysUser *system.Admin) (chartInfo *data_manage.ChartInfo, err error, errMsg string, isSendEmail bool) {
+	isSendEmail = true
+
+	source := utils.CHART_SOURCE_CROSS_HEDGING
+
+	req.ChartName = strings.Trim(req.ChartName, " ")
+	if req.ChartName == "" {
+		errMsg = "请填写图表名称!"
+		err = errors.New(errMsg)
+		isSendEmail = false
+		return
+	}
+	if req.TagX <= 0 {
+		errMsg = "请选择X轴坐标的标签!"
+		err = errors.New(errMsg)
+		isSendEmail = false
+		return
+	}
+	if req.TagY <= 0 {
+		errMsg = "请选择Y轴坐标的标签!"
+		err = errors.New(errMsg)
+		isSendEmail = false
+		return
+	}
+	if req.CalculateValue <= 0 {
+		errMsg = "请设置时间长度!"
+		err = errors.New(errMsg)
+		isSendEmail = false
+		return
+	}
+	if req.CalculateUnit == `` {
+		errMsg = "请设置时间频度!"
+		err = errors.New(errMsg)
+		isSendEmail = false
+		return
+	}
+	// 品种配置
+	if len(req.VarietyList) < 0 {
+		errMsg = "请选择品种!"
+		err = errors.New(errMsg)
+		isSendEmail = false
+		return
+	}
+	// 日期配置
+	dateConfigList := len(req.DateConfigList)
+	if dateConfigList < 0 {
+		errMsg = "请选择日期!"
+		err = errors.New(errMsg)
+		isSendEmail = false
+		return
+	}
+	if dateConfigList > 5 {
+		errMsg = "日期数量已达上限!"
+		err = errors.New(errMsg)
+		isSendEmail = false
+		return
+	}
+
+	// 基础配置转string
+	extraConfigByte, err := json.Marshal(req)
+	if err != nil {
+		return
+	}
+
+	chartClassify, err := data_manage.GetCrossVarietyChartClassifyBySysUserId(sysUser.AdminId)
+	if err != nil {
+		if err.Error() != utils.ErrNoRow() {
+			errMsg = "获取分类信息失败"
+			err = errors.New("获取分类信息失败,Err:" + err.Error())
+			return
+		}
+
+		timestamp := strconv.FormatInt(time.Now().UnixNano(), 10)
+		chartClassify = &data_manage.ChartClassify{
+			ChartClassifyId:   0,
+			ChartClassifyName: sysUser.RealName,
+			ParentId:          0,
+			HasData:           0,
+			CreateTime:        time.Now(),
+			ModifyTime:        time.Now(),
+			SysUserId:         sysUser.AdminId,
+			SysUserRealName:   sysUser.RealName,
+			Level:             1,
+			UniqueCode:        utils.MD5(utils.DATA_PREFIX + "_" + timestamp),
+			Sort:              0,
+			Source:            source,
+		}
+	}
+
+	var chartInfoId int
+	// 判断图表是否存在
+	//var condition string
+	//var pars []interface{}
+	//condition += " AND chart_name=? AND source = ? "
+	//pars = append(pars, req.ChartName, source)
+	//count, err := data_manage.GetChartInfoCountByCondition(condition, pars)
+	//if err != nil {
+	//	errMsg = "判断图表名称是否存在失败"
+	//	err = errors.New("判断图表名称是否存在失败,Err:" + err.Error())
+	//	return
+	//}
+
+	//if count > 0 {
+	//	errMsg = "图表已存在,请重新填写"
+	//	err = errors.New(errMsg)
+	//	isSendEmail = false
+	//	return
+	//}
+
+	chartInfo = new(data_manage.ChartInfo)
+	chartInfo.ChartName = req.ChartName
+	//chartInfo.EdbInfoIds = edbInfoIdStr
+	//chartInfo.ChartClassifyId = req.ChartClassifyId
+	chartInfo.SysUserId = sysUser.AdminId
+	chartInfo.SysUserRealName = sysUser.RealName
+	chartInfo.CreateTime = time.Now()
+	chartInfo.ModifyTime = time.Now()
+	chartInfo.IsSetName = 0
+	timestamp := strconv.FormatInt(time.Now().UnixNano(), 10)
+	chartInfo.UniqueCode = utils.MD5(utils.CHART_PREFIX + "_" + timestamp)
+	chartInfo.ChartType = 9 // 相关性图
+	chartInfo.Calendar = "公历"
+	chartInfo.DateType = 6
+	//chartInfo.StartDate = req.StartDate
+	//chartInfo.EndDate = req.EndDate
+	//chartInfo.SeasonStartDate = req.StartDate
+	//chartInfo.SeasonEndDate = req.EndDate
+	chartInfo.LeftMin = req.LeftMin
+	chartInfo.LeftMax = req.LeftMax
+	//chartInfo.RightMin = req.RightMin
+	//chartInfo.RightMax = req.RightMax
+	//chartInfo.Disabled = disableVal
+	chartInfo.Source = source
+	chartInfo.ExtraConfig = string(extraConfigByte)
+
+	// 图表品种
+	chartVarietyMappingList := make([]*cross_varietyModel.ChartVarietyMapping, 0)
+	for _, varietyId := range req.VarietyList {
+		chartVarietyMappingList = append(chartVarietyMappingList, &cross_varietyModel.ChartVarietyMapping{
+			Id:             0,
+			ChartInfoId:    0,
+			ChartVarietyId: varietyId,
+			ModifyTime:     time.Now(),
+			CreateTime:     time.Now(),
+		})
+	}
+
+	// 图表配置
+	chartInfoCrossVariety := &cross_varietyModel.ChartInfoCrossVariety{
+		Id:             0,
+		ChartInfoId:    0,
+		ChartXTagId:    req.TagX,
+		ChartYTagId:    req.TagY,
+		CalculateValue: req.CalculateValue,
+		CalculateUnit:  req.CalculateUnit,
+		ModifyTime:     time.Now(),
+		CreateTime:     time.Now(),
+	}
+
+	// 新增图表和指标mapping
+	chartInfoId, e := cross_varietyModel.CreateChart(chartInfo, chartClassify, chartVarietyMappingList, chartInfoCrossVariety)
+	if e != nil {
+		errMsg = "操作失败"
+		err = errors.New("新增相关性图表失败, Err: " + e.Error())
+		return
+	}
+
+	//添加es数据
+	go data.EsAddOrEditChartInfo(chartInfoId)
+
+	return
+}
+
+// EditChartInfo
+// @Description: 编辑图表
+// @author: Roc
+// @datetime 2023-11-24 15:58:31
+// @param req request.EditChartReq
+// @param sysUser *system.Admin
+// @return chartItem *data_manage.ChartInfo
+// @return err error
+// @return errMsg string
+// @return isSendEmail bool
+func EditChartInfo(req request.EditChartReq, sysUser *system.Admin) (chartItem *data_manage.ChartInfo, err error, errMsg string, isSendEmail bool) {
+	isSendEmail = true
+
+	chartItem, err = data_manage.GetChartInfoById(req.ChartInfoId)
+	if err != nil {
+		if err.Error() == utils.ErrNoRow() {
+			errMsg = "图表已被删除,请刷新页面"
+			err = errors.New(errMsg)
+			isSendEmail = false
+			return
+		}
+		errMsg = "获取图表信息失败"
+		err = errors.New("获取图表信息失败,Err:" + err.Error())
+		return
+	}
+
+	if chartItem.Source != utils.CHART_SOURCE_CROSS_HEDGING {
+		errMsg = "该图不是跨品种分析图表!"
+		err = errors.New(errMsg)
+		isSendEmail = false
+		return
+	}
+
+	req.ChartName = strings.Trim(req.ChartName, " ")
+	if req.ChartName == "" {
+		errMsg = "请填写图表名称!"
+		err = errors.New(errMsg)
+		isSendEmail = false
+		return
+	}
+	if req.TagX <= 0 {
+		errMsg = "请选择X轴坐标的标签!"
+		err = errors.New(errMsg)
+		isSendEmail = false
+		return
+	}
+	if req.TagY <= 0 {
+		errMsg = "请选择Y轴坐标的标签!"
+		err = errors.New(errMsg)
+		isSendEmail = false
+		return
+	}
+	if req.CalculateValue <= 0 {
+		errMsg = "请设置时间长度!"
+		err = errors.New(errMsg)
+		isSendEmail = false
+		return
+	}
+	if req.CalculateUnit == `` {
+		errMsg = "请设置时间频度!"
+		err = errors.New(errMsg)
+		isSendEmail = false
+		return
+	}
+	// 品种配置
+	if len(req.VarietyList) < 0 {
+		errMsg = "请选择品种!"
+		err = errors.New(errMsg)
+		isSendEmail = false
+		return
+	}
+	// 日期配置
+	dateConfigList := len(req.DateConfigList)
+	if dateConfigList < 0 {
+		errMsg = "请选择日期!"
+		err = errors.New(errMsg)
+		isSendEmail = false
+		return
+	}
+	if dateConfigList > 5 {
+		errMsg = "日期数量已达上限!"
+		err = errors.New(errMsg)
+		isSendEmail = false
+		return
+	}
+	// 基础配置转string
+	extraConfigByte, err := json.Marshal(req)
+	if err != nil {
+		return
+	}
+
+	// 图表操作权限
+	ok := data.CheckOpChartPermission(sysUser, chartItem.SysUserId)
+	if !ok {
+		errMsg = "没有该图表的操作权限"
+		err = errors.New(errMsg)
+		isSendEmail = false
+		return
+	}
+
+	//判断图表是否存在
+	//var condition string
+	//var pars []interface{}
+	//condition += " AND chart_info_id <> ? "
+	//pars = append(pars, req.ChartInfoId)
+	//condition += " AND chart_name=? AND source = ? "
+	//pars = append(pars, req.ChartName, chartItem.Source)
+	//count, err := data_manage.GetChartInfoCountByCondition(condition, pars)
+	//if err != nil {
+	//	errMsg = "判断图表名称是否存在失败"
+	//	err = errors.New("判断图表名称是否存在失败,Err:" + err.Error())
+	//	return
+	//}
+	//if count > 0 {
+	//	errMsg = "图表已存在,请重新填写"
+	//	err = errors.New(errMsg)
+	//	isSendEmail = false
+	//	return
+	//}
+
+	chartItem.ChartName = req.ChartName
+	chartItem.ExtraConfig = string(extraConfigByte)
+	chartItem.ModifyTime = time.Now()
+	chartUpdateCols := []string{"ChartName", "ExtraConfig", "ModifyTime"}
+
+	// 跨品种分析配置
+	chartInfoCrossVariety, err := cross_varietyModel.GetChartInfoCrossVarietyByChartInfoId(chartItem.ChartInfoId)
+	if err != nil {
+		return
+	}
+	chartInfoCrossVariety.ChartXTagId = req.TagX
+	chartInfoCrossVariety.ChartYTagId = req.TagY
+	chartInfoCrossVariety.CalculateValue = req.CalculateValue
+	chartInfoCrossVariety.CalculateUnit = req.CalculateUnit
+	chartInfoCrossVariety.ModifyTime = time.Now()
+	chartInfoCrossVarietyUpdateCols := []string{"ChartXTagId", "ChartYTagId", "CalculateValue", "CalculateUnit", "ModifyTime"}
+
+	// 图表品种
+	chartVarietyMappingList := make([]*cross_varietyModel.ChartVarietyMapping, 0)
+	for _, varietyId := range req.VarietyList {
+		chartVarietyMappingList = append(chartVarietyMappingList, &cross_varietyModel.ChartVarietyMapping{
+			Id:             0,
+			ChartInfoId:    0,
+			ChartVarietyId: varietyId,
+			ModifyTime:     time.Now(),
+			CreateTime:     time.Now(),
+		})
+	}
+
+	err = cross_varietyModel.EditChart(chartItem, chartVarietyMappingList, chartInfoCrossVariety,
+		chartUpdateCols, chartInfoCrossVarietyUpdateCols)
+	if err != nil {
+		errMsg = "保存失败"
+		err = errors.New("保存失败,Err:" + err.Error())
+		return
+	}
+
+	resp := new(data_manage.AddChartInfoResp)
+	resp.ChartInfoId = chartItem.ChartInfoId
+	resp.UniqueCode = chartItem.UniqueCode
+	//resp.ChartType = req.ChartType
+
+	//添加es数据
+	go data.EsAddOrEditChartInfo(chartItem.ChartInfoId)
+	//修改my eta es数据
+	go data.EsAddOrEditMyChartInfoByChartInfoId(chartItem.ChartInfoId)
+
+	return
+}

+ 3 - 2
services/data/edb_classify.go

@@ -4,6 +4,7 @@ import (
 	"errors"
 	"eta/eta_mobile/models/data_manage"
 	"eta/eta_mobile/models/system"
+	"eta/eta_mobile/services/data_stat"
 	"eta/eta_mobile/utils"
 	"strconv"
 	"time"
@@ -445,13 +446,13 @@ func Delete(classifyId, edbInfoId int, sysUser *system.Admin, requestBody, reque
 		}
 
 		//真实删除
-		tmpErr = data_manage.DeleteEdbInfoAndData(edbInfo.EdbInfoId, edbInfo.Source)
+		tmpErr = data_manage.DeleteEdbInfoAndData(edbInfo.EdbInfoId, edbInfo.Source, edbInfo.SubSource)
 		if tmpErr != nil {
 			errMsg = "删除失败"
 			err = errors.New("删除失败,Err:" + tmpErr.Error())
 			return
 		}
-
+		go data_stat.AddEdbDeleteLog(edbInfo, sysUser)
 		// 返回下一个表格的信息
 		{
 			var condition string

+ 2 - 2
services/data/edb_data.go

@@ -135,7 +135,7 @@ func GetChartEdbSeasonalData(calendar, startDate, endDate string, edbInfo *data_
 
 	switch edbInfo.EdbInfoType {
 	case 0:
-		dataList, err = data_manage.GetEdbDataList(edbInfo.Source, edbInfo.EdbInfoId, startDateReal, endDate)
+		dataList, err = data_manage.GetEdbDataList(edbInfo.Source, edbInfo.SubSource, edbInfo.EdbInfoId, startDateReal, endDate)
 	case 1:
 		_, dataList, _, _, err, _ = GetPredictDataListByPredictEdbInfoId(edbInfo.EdbInfoId, startDateReal, endDate, false)
 	default:
@@ -272,7 +272,7 @@ func GetDateData(edbInfo *data_manage.EdbInfo, startDate, endDate string) (item
 	var dataList []*data_manage.EdbDataList
 	switch edbInfo.EdbInfoType {
 	case 0:
-		dataList, err = data_manage.GetEdbDataList(edbInfo.Source, edbInfo.EdbInfoId, startDate, endDate)
+		dataList, err = data_manage.GetEdbDataList(edbInfo.Source, edbInfo.SubSource, edbInfo.EdbInfoId, startDate, endDate)
 	case 1:
 		_, dataList, _, _, err, _ = GetPredictDataListByPredictEdbInfoId(edbInfo.EdbInfoId, startDate, endDate, false)
 	default:

+ 178 - 23
services/data/edb_info.go

@@ -298,10 +298,10 @@ func EdbInfoRefreshAllFromBaseV3Bak(edbInfoIdList []int, refreshAll, isSync bool
 //	@datetime2023-10-23 09:57:55
 //	@param edbInfoIdList []int
 //	@param refreshAll bool
-//	@param isSync bool
+//	@param isSync bool 是否同步执行
 //	@return err error
-//	@return isAsync bool
-func EdbInfoRefreshAllFromBaseV3(edbInfoIdList []int, refreshAll bool, isSync bool) (err error, isAsync bool) {
+//	@return isAsync bool 是否异步刷新
+func EdbInfoRefreshAllFromBaseV3(edbInfoIdList []int, refreshAll, isSync bool) (err error, isAsync bool) {
 	var errmsg string
 	defer func() {
 		if err != nil {
@@ -309,6 +309,35 @@ func EdbInfoRefreshAllFromBaseV3(edbInfoIdList []int, refreshAll bool, isSync bo
 			go alarm_msg.SendAlarmMsg("EdbInfoRefreshAllFromBaseV3,Err"+err.Error()+";errMsg:"+errmsg, 3)
 		}
 	}()
+
+	// 获取需要刷新的指标列表
+	newBaseEdbInfoArr, newBasePredictEdbInfoArr, newCalculateMap, newPredictCalculateMap, calculateArr, predictCalculateArr := getEdbInfoIdList(edbInfoIdList)
+
+	// 需要刷新的指标数量
+	totalEdbInfo := len(newBaseEdbInfoArr) + len(calculateArr) + len(predictCalculateArr)
+
+	if totalEdbInfo <= 20 || isSync {
+		err = edbInfoRefreshAll(refreshAll, newBaseEdbInfoArr, newBasePredictEdbInfoArr, newCalculateMap, newPredictCalculateMap, calculateArr, predictCalculateArr)
+	} else {
+		isAsync = true
+		go edbInfoRefreshAll(refreshAll, newBaseEdbInfoArr, newBasePredictEdbInfoArr, newCalculateMap, newPredictCalculateMap, calculateArr, predictCalculateArr)
+	}
+
+	return
+}
+
+// getEdbInfoIdList
+// @Description: 获取待更新的指标列表
+// @author: Roc
+// @datetime 2023-12-01 16:19:42
+// @param edbInfoIdList []int
+// @return newBaseEdbInfoArr []*data_manage.EdbInfo
+// @return newBasePredictEdbInfoArr []*data_manage.EdbInfo
+// @return newCalculateMap map[int]*data_manage.EdbInfo
+// @return newPredictCalculateMap map[int]*data_manage.EdbInfo
+// @return calculateArr []int
+// @return predictCalculateArr []int
+func getEdbInfoIdList(edbInfoIdList []int) (newBaseEdbInfoArr, newBasePredictEdbInfoArr []*data_manage.EdbInfo, newCalculateMap, newPredictCalculateMap map[int]*data_manage.EdbInfo, calculateArr, predictCalculateArr []int) {
 	traceEdbInfoList, err := TraceEdbInfoByEdbInfoIdList(edbInfoIdList)
 	if err != nil {
 		return
@@ -317,16 +346,16 @@ func EdbInfoRefreshAllFromBaseV3(edbInfoIdList []int, refreshAll bool, isSync bo
 	existEdbInfoIdMap := make(map[int]int)
 
 	// 基础指标
-	newBaseEdbInfoArr := make([]*data_manage.EdbInfo, 0)
-	newBasePredictEdbInfoArr := make([]*data_manage.EdbInfo, 0)
+	newBaseEdbInfoArr = make([]*data_manage.EdbInfo, 0)
+	newBasePredictEdbInfoArr = make([]*data_manage.EdbInfo, 0)
 	newBaseMap := make(map[int]*data_manage.EdbInfo)
 	newPredictBaseMap := make(map[int]*data_manage.EdbInfo)
 
 	// 计算指标
-	newCalculateMap := make(map[int]*data_manage.EdbInfo)
-	newPredictCalculateMap := make(map[int]*data_manage.EdbInfo)
-	calculateArr := make([]int, 0)
-	predictCalculateArr := make([]int, 0)
+	newCalculateMap = make(map[int]*data_manage.EdbInfo)
+	newPredictCalculateMap = make(map[int]*data_manage.EdbInfo)
+	calculateArr = make([]int, 0)
+	predictCalculateArr = make([]int, 0)
 
 	// 获取关联指标
 	for _, traceEdbInfo := range traceEdbInfoList {
@@ -370,16 +399,6 @@ func EdbInfoRefreshAllFromBaseV3(edbInfoIdList []int, refreshAll bool, isSync bo
 	// 预测计算指标的id
 	sort.Ints(predictCalculateArr)
 
-	// 需要刷新的指标数量
-	totalEdbInfo := len(newBaseEdbInfoArr) + len(calculateArr) + len(predictCalculateArr)
-
-	if totalEdbInfo <= 20 || isSync {
-		err = edbInfoRefreshAll(refreshAll, newBaseEdbInfoArr, newBasePredictEdbInfoArr, newCalculateMap, newPredictCalculateMap, calculateArr, predictCalculateArr)
-	} else {
-		isAsync = true
-		go edbInfoRefreshAll(refreshAll, newBaseEdbInfoArr, newBasePredictEdbInfoArr, newCalculateMap, newPredictCalculateMap, calculateArr, predictCalculateArr)
-	}
-
 	return
 }
 
@@ -990,7 +1009,7 @@ func DeleteEdbInfoToEs(edbInfoId int) {
 }
 
 // EdbInfoAdd 添加指标到指标库
-func EdbInfoAdd(source, classifyId int, edbCode, edbName, frequency, unit, startDate, endDate string, sysUserId int, sysUserRealName string) (edbInfo *data_manage.EdbInfo, err error, errMsg string, isSendEmail bool) {
+func EdbInfoAdd(source, subSource, classifyId int, edbCode, edbName, frequency, unit, startDate, endDate string, sysUserId int, sysUserRealName string) (edbInfo *data_manage.EdbInfo, err error, errMsg string, isSendEmail bool) {
 	isSendEmail = true
 	//判断指标名称是否存在
 	var condition string
@@ -1098,7 +1117,7 @@ func EdbInfoAdd(source, classifyId int, edbCode, edbName, frequency, unit, start
 	edbInfo.DataDateType = `交易日`
 	timestamp := strconv.FormatInt(time.Now().UnixNano(), 10)
 	edbInfo.UniqueCode = utils.MD5(utils.DATA_PREFIX + "_" + timestamp)
-	itemVal, err := data_manage.GetEdbInfoMaxAndMinInfo(source, edbCode)
+	itemVal, err := data_manage.GetEdbInfoMaxAndMinInfo(source, subSource, edbCode)
 	if itemVal != nil && err == nil {
 		edbInfo.MaxValue = itemVal.MaxValue
 		edbInfo.MinValue = itemVal.MinValue
@@ -1112,7 +1131,7 @@ func EdbInfoAdd(source, classifyId int, edbCode, edbName, frequency, unit, start
 	}
 	edbInfo.EdbInfoId = int(edbInfoId)
 	//保存数据
-	data_manage.ModifyEdbInfoDataStatus(edbInfoId, source, edbCode)
+	data_manage.ModifyEdbInfoDataStatus(edbInfoId, source, subSource, edbCode)
 
 	//处理同名指标
 	//{
@@ -1141,7 +1160,7 @@ func EdbInfoAdd(source, classifyId int, edbCode, edbName, frequency, unit, start
 	//
 	//go data.EsAddOrEditEdbInfo(indexName, docId, edbInfo)
 
-	maxAndMinItem, _ := data_manage.GetEdbInfoMaxAndMinInfo(source, edbCode)
+	maxAndMinItem, _ := data_manage.GetEdbInfoMaxAndMinInfo(source, subSource, edbCode)
 	if maxAndMinItem != nil {
 		err = data_manage.ModifyEdbInfoMaxAndMinInfo(int(edbInfoId), maxAndMinItem)
 	}
@@ -1523,3 +1542,139 @@ func getEdbRuleTitle(edbInfo, parentEdbInfo *data_manage.EdbInfo, childList []da
 
 	return
 }
+
+// EdbInfoAdd 添加指标到指标库
+func EdbInfoWsdAdd(item *data_manage.EdbInfo) (edbInfo *data_manage.EdbInfo, err error, errMsg string, isSendEmail bool) {
+	isSendEmail = true
+	//判断指标名称是否存在
+	var condition string
+	var pars []interface{}
+
+	condition += " AND edb_name=? "
+	pars = append(pars, item.EdbName)
+
+	count, err := data_manage.GetEdbInfoCountByCondition(condition, pars)
+	if err != nil {
+		errMsg = "判断指标名称是否存在失败"
+		err = errors.New("判断指标名称是否存在失败,Err:" + err.Error())
+		return
+	}
+
+	if count > 0 {
+		errMsg = "指标名称已存在,请重新填写"
+		err = errors.New(errMsg)
+		isSendEmail = false
+		return
+	}
+
+	source := item.Source
+
+	edbInfo = new(data_manage.EdbInfo)
+	edbInfo.Source = source
+	sourceNameMap := map[int]string{
+		utils.DATA_SOURCE_THS:                 "同花顺",
+		utils.DATA_SOURCE_WIND:                "wind",
+		utils.DATA_SOURCE_PB:                  "彭博",
+		utils.DATA_SOURCE_PB_FINANCE:          "彭博财务",
+		utils.DATA_SOURCE_MANUAL:              "手工数据",
+		utils.DATA_SOURCE_LZ:                  "隆众",
+		utils.DATA_SOURCE_YS:                  "SMM",
+		utils.DATA_SOURCE_GL:                  "钢联",
+		utils.DATA_SOURCE_ZZ:                  "郑商所",
+		utils.DATA_SOURCE_DL:                  "大商所",
+		utils.DATA_SOURCE_SH:                  "上期所",
+		utils.DATA_SOURCE_CFFEX:               "中金所",
+		utils.DATA_SOURCE_SHFE:                "上期能源",
+		utils.DATA_SOURCE_GIE:                 "欧洲天然气",
+		utils.DATA_SOURCE_LT:                  "路透",
+		utils.DATA_SOURCE_COAL:                "中国煤炭网",
+		utils.DATA_SOURCE_GOOGLE_TRAVEL:       "our world in data",
+		utils.DATA_SOURCE_MYSTEEL_CHEMICAL:    "钢联化工",
+		utils.DATA_SOURCE_EIA_STEO:            "EIA STEO报告",
+		utils.DATA_SOURCE_COM_TRADE:           "UN",
+		utils.DATA_SOURCE_SCI:                 "SCI",
+		utils.DATA_SOURCE_BAIINFO:             "BAIINFO",
+		utils.DATA_SOURCE_STOCK_PLANT:         "存量装置",
+		utils.DATA_SOURCE_NATIONAL_STATISTICS: "国家统计局",
+		utils.DATA_SOURCE_FUBAO:               "富宝数据",
+	}
+
+	sourceName, ok := sourceNameMap[source]
+	if !ok {
+		edbSource := data_manage.EdbSourceIdMap[source]
+		if edbSource != nil {
+			sourceName = edbSource.SourceName
+		}
+		if sourceName == "" {
+			errMsg = "指标来源异常"
+			err = errors.New(errMsg)
+			return
+		}
+	}
+	edbInfo.SourceName = sourceName
+
+	edbType := 1 //基础指标
+	if source == utils.DATA_SOURCE_STOCK_PLANT {
+		edbType = 2 //计算指标
+	}
+	//从缓存中获取
+	serverUrl := ``
+	if edbInfo.Source == utils.DATA_SOURCE_WIND {
+		windCacheKey := utils.CACHE_WIND_URL + ":" + item.EdbCode
+		serverUrl, _ = utils.Rc.RedisString(windCacheKey)
+		if serverUrl == `` {
+			if len(utils.Hz_Data_WIND_Url_List) >= 1 {
+				serverUrl = utils.Hz_Data_WIND_Url_List[len(utils.Hz_Data_WIND_Url_List)-1] //默认是最后一个服务器地址
+			}
+		}
+	}
+	//获取该层级下最大的排序数
+	maxSort, err := GetEdbClassifyMaxSort(item.ClassifyId, 0)
+	if err != nil {
+		errMsg = "获取失败"
+		err = errors.New("查询排序信息失败,Err:" + err.Error())
+		return
+	}
+
+	edbInfo.EdbCode = item.EdbCode
+	edbInfo.EdbName = item.EdbName
+	edbInfo.EdbNameSource = item.EdbName
+	edbInfo.Frequency = item.Frequency
+	edbInfo.Unit = item.Unit
+	edbInfo.ClassifyId = item.ClassifyId
+	edbInfo.SysUserId = item.SysUserId
+	edbInfo.SysUserRealName = item.SysUserRealName
+	edbInfo.CreateTime = time.Now()
+	edbInfo.ModifyTime = time.Now()
+	edbInfo.ServerUrl = serverUrl
+	edbInfo.Sort = maxSort + 1
+	edbInfo.DataDateType = `交易日`
+	timestamp := strconv.FormatInt(time.Now().UnixNano(), 10)
+	edbInfo.UniqueCode = utils.MD5(utils.DATA_PREFIX + "_" + timestamp)
+	edbInfo.EdbType = edbType
+	edbInfo.SubSource = item.SubSource
+	edbInfo.SubSourceName = "日期序列"
+	edbInfo.IndicatorCode = item.IndicatorCode
+	edbInfo.StockCode = item.StockCode
+	edbInfoId, err := data_manage.AddEdbInfo(edbInfo)
+	if err != nil {
+		errMsg = "保存失败"
+		err = errors.New("保存失败,Err:" + err.Error())
+		return
+	}
+	edbInfo.EdbInfoId = int(edbInfoId)
+	//保存数据
+	err = data_manage.ModifyEdbInfoWindWsdDataStatus(source, item.SubSource, edbInfoId, item.EdbCode)
+	if err != nil {
+		errMsg = "保存失败"
+		err = errors.New("修改数据对应指标ID失败,Err:" + err.Error())
+		return
+	}
+	maxAndMinItem, _ := data_manage.GetEdbInfoWsdMaxAndMinInfo(source, item.SubSource, item.EdbCode)
+	if maxAndMinItem != nil {
+		err = data_manage.ModifyEdbInfoMaxAndMinInfo(int(edbInfoId), maxAndMinItem)
+	}
+	//添加es
+	AddOrEditEdbInfoToEs(int(edbInfoId))
+	return
+}

+ 2 - 2
services/data/edb_info_calculate.go

@@ -121,7 +121,7 @@ func Calculate(edbInfoIdArr []*data_manage.EdbInfo, edbInfoId int, edbCode, form
 		var pars []interface{}
 		condition += " AND edb_info_id=? "
 		pars = append(pars, v.EdbInfoId)
-		dataList, err := data_manage.GetEdbDataListAll(condition, pars, v.Source, 1)
+		dataList, err := data_manage.GetEdbDataListAll(condition, pars, v.Source, v.SubSource, 1)
 		if err != nil {
 			return err
 		}
@@ -515,7 +515,7 @@ func RefreshCalculate(edbInfoIdArr []*data_manage.EdbInfo, edbInfoId int, edbCod
 			condition += " AND data_time<=? "
 			pars = append(pars, endDate)
 		}
-		dataList, err := data_manage.GetEdbDataListAll(condition, pars, v.Source, 1)
+		dataList, err := data_manage.GetEdbDataListAll(condition, pars, v.Source, v.SubSource, 1)
 		if err != nil {
 			return err
 		}

+ 1 - 1
services/data/future_good/chart_info.go

@@ -70,7 +70,7 @@ func GetChartEdbData(chartInfoId int, startDate, endDate string, edbInfoMapping,
 	{
 		dataList := make([]*data_manage.EdbDataList, 0)
 
-		dataList, err = data_manage.GetEdbDataList(edbInfoMapping.Source, edbInfoMapping.EdbInfoId, startDate, endDate)
+		dataList, err = data_manage.GetEdbDataList(edbInfoMapping.Source, edbInfoMapping.SubSource, edbInfoMapping.EdbInfoId, startDate, endDate)
 		edbDataListMap[edbInfoMapping.EdbInfoId] = dataList
 		item.DataList = dataList
 

+ 3 - 3
services/data/predict_edb_info.go

@@ -415,13 +415,13 @@ func GetPredictDataListByPredictEdbInfo(edbInfo *data_manage.EdbInfo, startDate,
 
 	allDataList := make([]*data_manage.EdbDataList, 0)
 	//获取指标数据(实际已生成)
-	dataList, err = data_manage.GetEdbDataList(sourceEdbInfoItem.Source, sourceEdbInfoItem.EdbInfoId, startDate, endDate)
+	dataList, err = data_manage.GetEdbDataList(sourceEdbInfoItem.Source, sourceEdbInfoItem.SubSource, sourceEdbInfoItem.EdbInfoId, startDate, endDate)
 	if err != nil {
 		return
 	}
 	// 如果选择了日期,那么需要筛选所有的数据,用于未来指标的生成
 	if startDate != `` {
-		allDataList, err = data_manage.GetEdbDataList(sourceEdbInfoItem.Source, sourceEdbInfoItem.EdbInfoId, "", "")
+		allDataList, err = data_manage.GetEdbDataList(sourceEdbInfoItem.Source, sourceEdbInfoItem.SubSource, sourceEdbInfoItem.EdbInfoId, "", "")
 		if err != nil {
 			return
 		}
@@ -606,7 +606,7 @@ func GetChartDataList(dataList []*data_manage.EdbDataList, chartType int, calend
 
 // GetPredictCalculateDataListByPredictEdbInfo 根据预测运算指标信息获取预测指标的数据
 func GetPredictCalculateDataListByPredictEdbInfo(edbInfo *data_manage.EdbInfo, startDate, endDate string) (dataList []*data_manage.EdbDataList, sourceEdbInfoItem *data_manage.EdbInfo, predictEdbConf *data_manage.PredictEdbConf, err error, errMsg string) {
-	dataList, err = data_manage.GetEdbDataList(edbInfo.Source, edbInfo.EdbInfoId, startDate, endDate)
+	dataList, err = data_manage.GetEdbDataList(edbInfo.Source, edbInfo.SubSource, edbInfo.EdbInfoId, startDate, endDate)
 	return
 }
 

+ 1 - 1
services/data/predict_edb_info_rule.go

@@ -1339,7 +1339,7 @@ func getCalculateNhccData(secondDataList []*data_manage.EdbDataList, ruleConf Ru
 		var firstDataList []*data_manage.EdbDataList
 		switch edbInfo.EdbInfoType {
 		case 0:
-			firstDataList, err = data_manage.GetEdbDataList(edbInfo.Source, edbInfo.EdbInfoId, ``, ``)
+			firstDataList, err = data_manage.GetEdbDataList(edbInfo.Source, edbInfo.SubSource, edbInfo.EdbInfoId, ``, ``)
 		case 1:
 			_, firstDataList, _, _, err, _ = GetPredictDataListByPredictEdbInfoId(edbInfo.EdbInfoId, ``, ``, false)
 		default:

+ 61 - 0
services/data_stat/edb_delete_log.go

@@ -0,0 +1,61 @@
+package data_stat
+
+import (
+	"eta/eta_mobile/models/data_manage"
+	"eta/eta_mobile/models/data_stat"
+	"eta/eta_mobile/models/system"
+	"eta/eta_mobile/utils"
+	"fmt"
+	"time"
+)
+
+func AddEdbDeleteLog(edbInfo *data_manage.EdbInfo, sysUser *system.Admin) (err error) {
+	if edbInfo != nil {
+		log := new(data_stat.EdbInfoDeleteLog)
+		log.EdbInfoId = edbInfo.EdbInfoId
+		log.EdbInfoType = edbInfo.EdbInfoType
+		log.SourceName = edbInfo.SourceName
+		log.Source = edbInfo.Source
+		log.EdbCode = edbInfo.EdbCode
+		log.EdbName = edbInfo.EdbName
+		log.EdbNameEn = edbInfo.EdbNameEn
+		log.EdbNameSource = edbInfo.SourceIndexName
+		log.Frequency = edbInfo.Frequency
+		log.Unit = edbInfo.Unit
+		log.UnitEn = edbInfo.UnitEn
+		log.StartDate = edbInfo.StartDate
+		log.EndDate = edbInfo.EndDate
+		log.SysUserId = edbInfo.SysUserId
+		log.SysUserRealName = edbInfo.SysUserRealName
+		log.UniqueCode = edbInfo.UniqueCode
+		log.EdbCreateTime = edbInfo.CreateTime.Format(utils.FormatDateTime)
+		log.EdbModifyTime = edbInfo.ModifyTime.Format(utils.FormatDateTime)
+		log.CreateTime = time.Now().Format(utils.FormatDateTime)
+		log.MinValue = edbInfo.MinValue
+		log.MaxValue = edbInfo.MaxValue
+		log.CalculateFormula = edbInfo.CalculateFormula
+		log.EdbType = edbInfo.EdbType
+		log.LatestDate = edbInfo.LatestDate
+		log.LatestValue = edbInfo.LatestValue
+		log.MoveType = edbInfo.MoveType
+		log.MoveFrequency = edbInfo.MoveFrequency
+		log.NoUpdate = edbInfo.NoUpdate
+		log.ChartImage = edbInfo.ChartImage
+		log.Calendar = edbInfo.Calendar
+		log.DataDateType = edbInfo.DataDateType
+		log.ManualSave = edbInfo.ManualSave
+		log.TerminalCode = edbInfo.TerminalCode
+
+		log.DelSysUserId = sysUser.AdminId
+		log.DelSysUserRealName = sysUser.RealName
+		log.DataUpdateTime = edbInfo.DataUpdateTime
+		log.ErDataUpdateDate = edbInfo.ErDataUpdateDate
+
+		_, err = data_stat.AddEdbDeleteLog(log)
+		if err != nil {
+			err = fmt.Errorf("新增指标删除日志失败,Err: %s", err)
+			return
+		}
+	}
+	return
+}

+ 55 - 0
services/data_stat/edb_info_stat.go

@@ -0,0 +1,55 @@
+package data_stat
+
+import (
+	"eta/eta_mobile/models/data_manage"
+	"eta/eta_mobile/models/data_stat"
+	"eta/eta_mobile/models/system"
+	"fmt"
+	"time"
+)
+
+// AddEdbInfoUpdateLog 添加指标编辑/刷新日志
+func AddEdbInfoUpdateLog(edbInfoId int, updateResult int, updateFailedReason string, sysUser *system.Admin) (err error) {
+	var edbInfo *data_manage.EdbInfo
+	if edbInfoId > 0 {
+		// 获取指标详情
+		edbInfo, err = data_manage.GetEdbInfoById(edbInfoId)
+		if err != nil {
+			err = fmt.Errorf("指标不存在")
+			return
+		}
+		nowTime := time.Now()
+		log := new(data_stat.EdbInfoUpdateLog)
+		log.EdbInfoId = edbInfo.EdbInfoId
+		log.SourceName = edbInfo.SourceName
+		log.Source = edbInfo.Source
+		log.EdbCode = edbInfo.EdbCode
+		log.EdbName = edbInfo.EdbName
+		log.EdbNameSource = edbInfo.SourceIndexName
+		log.Frequency = edbInfo.Frequency
+		log.Unit = edbInfo.Unit
+		log.StartDate = edbInfo.StartDate
+		log.EndDate = edbInfo.EndDate
+		log.SysUserId = edbInfo.SysUserId
+		log.SysUserRealName = edbInfo.SysUserRealName
+		log.UpdateSysUserId = sysUser.AdminId
+		log.UpdateSysUserRealName = sysUser.RealName
+		log.UniqueCode = edbInfo.UniqueCode
+		log.EdbCreateTime = edbInfo.CreateTime
+		log.EdbModifyTime = edbInfo.ModifyTime
+		log.CreateTime = nowTime
+		log.LatestDate = edbInfo.LatestDate
+		log.LatestValue = edbInfo.LatestValue
+		log.TerminalCode = edbInfo.TerminalCode
+		log.UpdateResult = updateResult
+		log.UpdateFailedReason = updateFailedReason
+		log.DataUpdateTime = edbInfo.DataUpdateTime
+		log.ErDataUpdateDate = edbInfo.ErDataUpdateDate
+		_, err = data_stat.AddEdbUpdateLog(log)
+		if err != nil {
+			err = fmt.Errorf("新增指标更新日志失败,Err: %s", err)
+			return
+		}
+	}
+	return
+}

+ 24 - 7
utils/constants.go

@@ -302,13 +302,14 @@ const (
 const (
 	CHART_SOURCE_DEFAULT                         = 1
 	CHART_SOURCE_FUTURE_GOOD                     = 2
-	CHART_SOURCE_CORRELATION                     = 3 // 相关性图表
-	CHART_SOURCE_ROLLING_CORRELATION             = 4 // 滚动相关性图表
-	CHART_SOURCE_FUTURE_GOOD_PROFIT              = 5 // 商品利润曲线
-	CHART_SOURCE_LINE_EQUATION                   = 6 // 拟合方程图表
-	CHART_SOURCE_LINE_FEATURE_STANDARD_DEVIATION = 7 // 统计特征-标准差图表
-	CHART_SOURCE_LINE_FEATURE_PERCENTILE         = 8 // 统计特征-百分位图表
-	CHART_SOURCE_LINE_FEATURE_FREQUENCY          = 9 // 统计特征-频率分布图表
+	CHART_SOURCE_CORRELATION                     = 3  // 相关性图表
+	CHART_SOURCE_ROLLING_CORRELATION             = 4  // 滚动相关性图表
+	CHART_SOURCE_FUTURE_GOOD_PROFIT              = 5  // 商品利润曲线
+	CHART_SOURCE_LINE_EQUATION                   = 6  // 拟合方程图表
+	CHART_SOURCE_LINE_FEATURE_STANDARD_DEVIATION = 7  // 统计特征-标准差图表
+	CHART_SOURCE_LINE_FEATURE_PERCENTILE         = 8  // 统计特征-百分位图表
+	CHART_SOURCE_LINE_FEATURE_FREQUENCY          = 9  // 统计特征-频率分布图表
+	CHART_SOURCE_CROSS_HEDGING                   = 10 // 跨品种分析图表
 )
 
 // 批量配置图表的位置来源
@@ -377,3 +378,19 @@ const (
 	STORAGESOURCE_OSS   = 1 //阿里云OSS
 	STORAGESOURCE_MINIO = 2 //MinIo
 )
+
+// 子数据来源渠道
+const (
+	DATA_SUB_SOURCE_EDB  = iota //经济数据库
+	DATA_SUB_SOURCE_DATE        //日期序列
+)
+
+const (
+	UserLoginSalt = "MiQM9yusNA9T2uIH"         // 用户登录盐值
+	DesKeySalt    = "JMCqSoUrTAmyNNIRb0TtlrPk" // DesKey盐值
+)
+
+const (
+	WindDbWsd = "wsd"
+	ThsDs = "thsds"
+)

+ 2 - 2
utils/des3.go

@@ -12,8 +12,8 @@ import (
 )
 
 // des3 + base64 encrypt
-func DesBase64Encrypt(origData []byte) []byte {
-	result, err := TripleDesEncrypt(origData, []byte(DesKey))
+func DesBase64Encrypt(origData []byte, desKey string) []byte {
+	result, err := TripleDesEncrypt(origData, []byte(desKey))
 	if err != nil {
 		panic(err)
 	}