Browse Source

Merge branch 'master' of http://8.136.199.33:3000/eta_server/eta_mobile into bzq/lib_record

zqbao 7 months ago
parent
commit
5361a2f083
96 changed files with 9645 additions and 5625 deletions
  1. 22 0
      cache/replace_edb_info.go
  2. 60 0
      controllers/data_manage/chart_common.go
  3. 70 62
      controllers/data_manage/chart_info.go
  4. 10 0
      controllers/data_manage/chart_theme.go
  5. 304 106
      controllers/data_manage/correlation/correlation_chart_info.go
  6. 27 25
      controllers/data_manage/cross_variety/chart_info.go
  7. 49 59
      controllers/data_manage/edb_info.go
  8. 8 4
      controllers/data_manage/edb_info_calculate.go
  9. 241 0
      controllers/data_manage/excel/balance_table.go
  10. 144 15
      controllers/data_manage/excel/excel_info.go
  11. 27 25
      controllers/data_manage/future_good/future_good_chart_info.go
  12. 27 25
      controllers/data_manage/future_good/future_good_profit_chart_info.go
  13. 27 25
      controllers/data_manage/line_equation/line_chart_info.go
  14. 27 25
      controllers/data_manage/line_feature/chart_info.go
  15. 2 0
      controllers/data_manage/my_chart.go
  16. 3 33
      controllers/data_manage/predict_edb_info.go
  17. 18 2
      controllers/data_manage/supply_analysis/variety_edb.go
  18. 13 0
      go.mod
  19. 38 0
      go.sum
  20. 16 0
      models/business_conf.go
  21. 231 0
      models/data_manage/base_from_business_data.go
  22. 252 0
      models/data_manage/base_from_business_index.go
  23. 10 0
      models/data_manage/chart_edb_mapping.go
  24. 331 44
      models/data_manage/chart_info.go
  25. 164 0
      models/data_manage/chart_info_correlation.go
  26. 85 0
      models/data_manage/chart_theme/request/theme.go
  27. 107 24
      models/data_manage/edb_data_base.go
  28. 0 174
      models/data_manage/edb_data_calculate.go
  29. 0 27
      models/data_manage/edb_data_calculate_ljztbpj.go
  30. 0 160
      models/data_manage/edb_data_calculate_time_shift.go
  31. 0 34
      models/data_manage/edb_data_calculate_zjpj.go
  32. 0 347
      models/data_manage/edb_data_cffex.go
  33. 0 227
      models/data_manage/edb_data_coal.go
  34. 1 54
      models/data_manage/edb_data_fubao.go
  35. 161 4
      models/data_manage/edb_data_insert_config.go
  36. 0 315
      models/data_manage/edb_data_lz.go
  37. 2 194
      models/data_manage/edb_data_quarter.go
  38. 0 87
      models/data_manage/edb_data_sci.go
  39. 0 63
      models/data_manage/edb_data_ths_ds.go
  40. 0 48
      models/data_manage/edb_data_wind_wsd.go
  41. 368 516
      models/data_manage/edb_info.go
  42. 3 91
      models/data_manage/edb_info_calculate.go
  43. 0 157
      models/data_manage/edb_info_calculate_bp.go
  44. 0 144
      models/data_manage/edb_info_calculate_hbz.go
  45. 0 149
      models/data_manage/edb_info_calculate_hcz.go
  46. 0 387
      models/data_manage/edb_info_calculate_ljztbpj.go
  47. 0 210
      models/data_manage/edb_info_calculate_ljzzy.go
  48. 0 173
      models/data_manage/edb_info_calculate_nszydpjjs.go
  49. 0 787
      models/data_manage/edb_info_calculate_tbz.go
  50. 0 256
      models/data_manage/edb_info_calculate_tcz.go
  51. 0 286
      models/data_manage/edb_info_calculate_zjpj.go
  52. 126 0
      models/data_manage/excel/excel_chart_data.go
  53. 366 0
      models/data_manage/excel/excel_chart_edb.go
  54. 46 16
      models/data_manage/excel/excel_info.go
  55. 82 0
      models/data_manage/excel/excel_worker.go
  56. 2 0
      models/data_manage/excel/request/excel_info.go
  57. 10 0
      models/data_manage/excel/request/mixed_table.go
  58. 41 28
      models/data_manage/excel/response/excel_info.go
  59. 17 17
      models/data_manage/excel/response/sheet.go
  60. 350 0
      models/data_manage/factor_edb_series.go
  61. 190 0
      models/data_manage/factor_edb_series_calculate_data.go
  62. 153 0
      models/data_manage/factor_edb_series_calculate_func.go
  63. 167 0
      models/data_manage/factor_edb_series_chart_mapping.go
  64. 167 0
      models/data_manage/factor_edb_series_mapping.go
  65. 26 8
      models/db.go
  66. 8 0
      models/english_report.go
  67. 419 0
      models/mgo/base_from_business_data.go
  68. 58 0
      models/mgo/common.go
  69. 511 0
      models/mgo/edb_data_business.go
  70. 274 0
      models/mgo_base.go
  71. 9 0
      models/report.go
  72. 9 0
      models/smart_report/smart_report.go
  73. 27 0
      routers/commentsRouter.go
  74. 25 0
      services/data/base_edb_lib.go
  75. 172 0
      services/data/base_from_business.go
  76. 1003 8
      services/data/chart_info.go
  77. 783 0
      services/data/chart_info_excel_balance.go
  78. 46 0
      services/data/chart_info_interface.go
  79. 57 0
      services/data/chart_theme.go
  80. 120 2
      services/data/correlation/chart_info.go
  81. 230 0
      services/data/edb_data.go
  82. 50 3
      services/data/edb_info.go
  83. 141 103
      services/data/edb_info_calculate.go
  84. 408 0
      services/data/excel/balance_table.go
  85. 106 3
      services/data/excel/excel_info.go
  86. 55 0
      services/data/factor_edb_series.go
  87. 58 14
      services/data/future_good/chart_info.go
  88. 4 2
      services/data/future_good/profit_chart_info.go
  89. 190 32
      services/elastic/elastic.go
  90. 18 3
      services/excel/lucky_sheet.go
  91. 59 19
      services/smart_report.go
  92. 22 0
      utils/common.go
  93. 14 3
      utils/config.go
  94. 4 0
      utils/constants.go
  95. 37 0
      utils/logs.go
  96. 137 0
      utils/mgodb/mgo_config.go

+ 22 - 0
cache/replace_edb_info.go

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

+ 60 - 0
controllers/data_manage/chart_common.go

@@ -1,6 +1,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"
@@ -8,7 +9,12 @@ import (
 	"eta/eta_mobile/controllers/data_manage/line_feature"
 	"eta/eta_mobile/models"
 	"eta/eta_mobile/models/data_manage"
+	"eta/eta_mobile/models/system"
+	"eta/eta_mobile/services/data"
+	"eta/eta_mobile/services/data/excel"
 	"eta/eta_mobile/utils"
+	"fmt"
+	"time"
 )
 
 // CommonChartInfoDetailFromUniqueCode
@@ -150,9 +156,63 @@ func (this *ChartInfoController) CommonChartInfoDetailFromUniqueCode() {
 		br.Success = true
 		br.Msg = "获取成功"
 		br.Data = resp
+	case utils.CHART_SOURCE_BALANCE_EXCEL:
+		resp, isOk, msg, errMsg := getBalanceChartInfoDetailFromUniqueCode(chartInfo, isCache, sysUser, this.Lang)
+		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 = "错误的图表"
 		return
 	}
 }
+
+func getBalanceChartInfoDetailFromUniqueCode(chartInfo *data_manage.ChartInfoView, isCache bool, sysUser *system.Admin, lang string) (resp *data_manage.ChartInfoDetailFromUniqueCodeResp, isOk bool, msg, errMsg string) {
+	resp = new(data_manage.ChartInfoDetailFromUniqueCodeResp)
+	resp, isOk, msg, errMsg = data.CheckBalanceChartCacheAndPermission(chartInfo, isCache, sysUser)
+	if isOk {
+		return
+	}
+	msg = `获取失败`
+	// 相关联指标
+	mappingListTmp, dataListMap, err, errMsg := excel.GetBalanceExcelChartSingle(chartInfo.ChartInfoId, 0, lang)
+	if err != nil {
+		errMsg = "获取失败"
+		err = fmt.Errorf(" 获取图表,指标信息失败 Err:%s", err.Error())
+		return
+	}
+	var chartInfoResp *data_manage.ChartInfoDetailResp
+	chartInfoResp, err, errMsg = data.GetBalanceExcelChartDetail(chartInfo, mappingListTmp, sysUser, dataListMap)
+	if err != nil {
+		msg = "查询图表详情失败"
+		errMsg = "查询图表详情失败,Err:" + err.Error()
+		return
+	}
+	resp = &data_manage.ChartInfoDetailFromUniqueCodeResp{
+		ChartInfo:            chartInfoResp.ChartInfo,
+		Status:               true,
+		EdbInfoList:          chartInfoResp.EdbInfoList,
+		XEdbIdValue:          chartInfoResp.XEdbIdValue,
+		YDataList:            chartInfoResp.YDataList,
+		XDataList:            chartInfoResp.XDataList,
+		BarChartInfo:         chartInfoResp.BarChartInfo,
+		CorrelationChartInfo: chartInfoResp.CorrelationChartInfo,
+		DataResp:             chartInfoResp.DataResp,
+	}
+	// 将数据加入缓存
+	if utils.Re == nil {
+		cacheData, _ := json.Marshal(resp)
+		key := data.GetChartInfoDataKey(chartInfo.ChartInfoId)
+		utils.Rc.Put(key, cacheData, 2*time.Hour)
+	}
+	isOk = true
+
+	return
+}

+ 70 - 62
controllers/data_manage/chart_info.go

@@ -10,6 +10,7 @@ import (
 	"eta/eta_mobile/services"
 	"eta/eta_mobile/services/data"
 	"eta/eta_mobile/services/data/data_manage_permission"
+	"eta/eta_mobile/services/data/excel"
 	etaTrialService "eta/eta_mobile/services/eta_trial"
 	"eta/eta_mobile/utils"
 	"fmt"
@@ -1012,19 +1013,12 @@ func (this *ChartInfoController) ChartInfoDetail() {
 			br.ErrMsg = "获取主题信息失败,Err:" + err.Error()
 			return
 		}
+
 		chartInfo.ChartThemeStyle = chartTheme.Config
 		chartInfo.ChartThemeId = chartTheme.ChartThemeId
 
 		// 图表数据权限
 		{
-			// 图表分类
-			chartClassify, err := data_manage.GetChartClassifyById(chartInfo.ChartClassifyId)
-			if err != nil {
-				br.Msg = "获取失败"
-				br.ErrMsg = "获取图表分类信息失败,Err:" + err.Error()
-				return
-			}
-
 			// 已授权分类id
 			permissionChartIdList, permissionClassifyIdList, err := data_manage_permission.GetUserChartAndClassifyPermissionList(this.SysUser.AdminId, chartInfo.ChartInfoId, chartInfo.ChartClassifyId)
 			if err != nil {
@@ -1032,19 +1026,53 @@ func (this *ChartInfoController) ChartInfoDetail() {
 				br.ErrMsg = "获取已授权分类id数据失败,Err:" + err.Error()
 				return
 			}
-			chartInfo.HaveOperaAuth = data_manage_permission.CheckChartPermissionByPermissionIdList(chartInfo.IsJoinPermission, chartClassify.IsJoinPermission, chartInfo.ChartInfoId, chartInfo.ChartClassifyId, permissionChartIdList, permissionClassifyIdList)
+			if chartInfo.ChartClassifyId > 0 {
+				// 图表分类
+				chartClassify, err := data_manage.GetChartClassifyById(chartInfo.ChartClassifyId)
+				if err != nil {
+					br.Msg = "获取失败"
+					br.ErrMsg = "获取图表分类信息失败,Err:" + err.Error()
+					return
+				}
+				chartInfo.HaveOperaAuth = data_manage_permission.CheckChartPermissionByPermissionIdList(chartInfo.IsJoinPermission, chartClassify.IsJoinPermission, chartInfo.ChartInfoId, chartInfo.ChartClassifyId, permissionChartIdList, permissionClassifyIdList)
+			} else {
+				chartInfo.HaveOperaAuth = data_manage_permission.CheckChartPermissionByPermissionIdList(chartInfo.IsJoinPermission, 0, chartInfo.ChartInfoId, chartInfo.ChartClassifyId, permissionChartIdList, permissionClassifyIdList)
+			}
+
 		}
 	}
 
 	resp := new(data_manage.ChartInfoDetailResp)
-
+	// 区分是否是来自平衡表图表的数据
+	var chartInfoDataShow data.ChartInfoDataShow
+	chartInfoDataShow = &data.BaseChartInfoDataShow{}
 	mappingList := make([]*data_manage.ChartEdbInfoMapping, 0)
 	if chartInfoId > 0 {
-		mappingList, err = data_manage.GetChartEdbMappingList(chartInfoId)
-		if err != nil {
-			br.Msg = "获取失败"
-			br.ErrMsg = "获取图表,指标信息失败,Err:" + err.Error()
-			return
+		if chartInfo.Source == utils.CHART_SOURCE_BALANCE_EXCEL { //来自平衡表图表的数据
+			excelChartInfoDataShow := new(data.ExcelChartInfoDataShow)
+			// 相关联指标
+			mappingListTmp, dataListMap, err, errMsg := excel.GetBalanceExcelChartSingle(chartInfoId, 0, "")
+			if err != nil {
+				br.Msg = errMsg
+				br.ErrMsg = err.Error()
+				return
+			}
+			excelChartInfoDataShow.DataListMap = dataListMap
+			excelChartInfoDataShow.MappingListTmp = mappingListTmp
+			chartInfoDataShow = excelChartInfoDataShow
+			mappingList, err = chartInfoDataShow.GetChartEdbMappingListByEdbInfoIdList([]int{})
+			if err != nil {
+				br.Msg = "获取失败"
+				br.ErrMsg = "获取图表,指标信息失败,Err:" + err.Error()
+				return
+			}
+		} else {
+			mappingList, err = data_manage.GetChartEdbMappingList(chartInfoId)
+			if err != nil {
+				br.Msg = "获取失败"
+				br.ErrMsg = "获取图表,指标信息失败,Err:" + err.Error()
+				return
+			}
 		}
 	} else {
 		if edbInfoId != "" {
@@ -1096,7 +1124,7 @@ func (this *ChartInfoController) ChartInfoDetail() {
 
 	if chartInfo.HaveOperaAuth {
 		// 获取图表中的指标数据
-		edbList, xEdbIdValue, yDataList, dataResp, err, errMsg := data.GetChartEdbData(chartInfoId, chartType, calendar, startDate, endDate, mappingList, extraConfigStr, chartInfo.SeasonExtraConfig)
+		edbList, xEdbIdValue, yDataList, dataResp, err, errMsg := data.GetChartEdbDataV2(chartInfoId, chartType, calendar, startDate, endDate, mappingList, extraConfigStr, chartInfo.SeasonExtraConfig, chartInfoDataShow)
 		if err != nil {
 			br.Msg = "获取失败"
 			if errMsg != `` {
@@ -1481,6 +1509,7 @@ func (this *ChartInfoController) ChartInfoDetailV2() {
 		br.ErrMsg = "获取主题信息失败,Err:" + err.Error()
 		return
 	}
+
 	chartInfo.ChartThemeStyle = chartTheme.Config
 	chartInfo.ChartThemeId = chartTheme.ChartThemeId
 
@@ -2457,7 +2486,6 @@ func (this *ChartInfoController) ChartInfoDetailFromUniqueCode() {
 
 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)
-
 	msg = `获取失败`
 	adminId := sysUser.AdminId
 
@@ -2480,6 +2508,28 @@ func GetChartInfoDetailFromUniqueCode(chartInfo *data_manage.ChartInfoView, isCa
 	edbClassifyPermissionMap := make(map[int]data_manage_permission.EdbClassifyPermission)
 	defer func() {
 		if isOk {
+			// 这里跟当前用户相关的信息重新查询写入resp, 不使用缓存中的
+			{
+				//判断是否加入我的图库
+				var myChartCondition string
+				var myChartPars []interface{}
+				myChartCondition += ` AND a.admin_id=? `
+				myChartPars = append(myChartPars, 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
+				}
+			}
 
 			// 图表权限校验
 			{
@@ -2575,50 +2625,6 @@ func GetChartInfoDetailFromUniqueCode(chartInfo *data_manage.ChartInfoView, isCa
 				if err != nil || resp == nil {
 					return
 				}
-				// 这里跟当前用户相关的信息重新查询写入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
-				}
-
-				//判断是否加入我的图库
-				{
-					var myChartCondition string
-					var myChartPars []interface{}
-					myChartCondition += ` AND a.admin_id=? `
-					myChartPars = append(myChartPars, 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
-					}
-				}
-
 				isOk = true
 				fmt.Println("source redis")
 				return
@@ -2633,6 +2639,7 @@ func GetChartInfoDetailFromUniqueCode(chartInfo *data_manage.ChartInfoView, isCa
 		errMsg = "获取主题信息失败,Err:" + err.Error()
 		return
 	}
+
 	chartInfo.ChartThemeStyle = chartTheme.Config
 	chartInfo.ChartThemeId = chartTheme.ChartThemeId
 
@@ -3879,6 +3886,7 @@ func (this *ChartInfoController) ChartInfoConvertDetail() {
 	convertValue, _ := this.GetFloat("ConvertValue")
 	convertUnit := this.GetString("ConvertUnit")
 	convertEnUnit := this.GetString("ConvertEnUnit")
+	isAxis, _ := this.GetInt("IsAxis")
 
 	resp := new(data_manage.ChartInfoDetailResp)
 	var err error
@@ -4010,7 +4018,7 @@ func (this *ChartInfoController) ChartInfoConvertDetail() {
 		startDate, endDate = utils.GetDateByDateTypeV2(dateType, startDate, endDate, startYear, yearMax)
 
 		// 获取图表中的指标数据
-		edbList, xEdbIdValue, yDataList, dataResp, err, errMsg := data.GetChartConvertEdbData(chartInfoId, chartType, calendar, startDate, endDate, mappingList, extraConfigStr, chartInfo.SeasonExtraConfig)
+		edbList, xEdbIdValue, yDataList, dataResp, err, errMsg := data.GetChartConvertEdbData(chartInfoId, chartType, calendar, startDate, endDate, mappingList, extraConfigStr, chartInfo.SeasonExtraConfig, isAxis)
 		if err != nil {
 			br.Msg = "获取失败"
 			if errMsg != `` {

+ 10 - 0
controllers/data_manage/chart_theme.go

@@ -52,6 +52,16 @@ func (c *ChartThemeController) List() {
 		return
 	}
 
+	// 兼容历史数据,加入新字段LineOptionList
+	for i, v := range list {
+		newConfig, e := data.ConvertOldChartOptions(v.Config)
+		if e != nil {
+			continue
+		}
+		list[i].Config = newConfig
+	}
+
+
 	br.Ret = 200
 	br.Success = true
 	br.Msg = "获取成功"

+ 304 - 106
controllers/data_manage/correlation/correlation_chart_info.go

@@ -1027,11 +1027,19 @@ func (this *CorrelationChartInfoController) Refresh() {
 	}
 
 	// 刷新相关性图表
-	if e := correlationServ.ChartInfoRefresh(chartInfo.ChartInfoId); e != nil {
+	isAsync, e := correlationServ.ChartInfoRefresh(chartInfo.ChartInfoId, chartInfo.UniqueCode)
+	if e != nil {
 		br.Msg = "刷新失败"
 		br.ErrMsg = "刷新相关性图表失败, Err:" + err.Error()
 		return
 	}
+	// 多因子相关性异步刷新, 前端提示
+	if isAsync {
+		br.Ret = 200
+		br.Success = true
+		br.Msg = "刷新时间较长, 请10分钟后查看"
+		return
+	}
 
 	//清除图表缓存
 	{
@@ -1053,10 +1061,12 @@ func (this *CorrelationChartInfoController) Refresh() {
 func (this *CorrelationChartInfoController) Copy() {
 	br := new(models.BaseResponse).Init()
 	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
 		this.Data["json"] = br
 		this.ServeJSON()
 	}()
-
 	sysUser := this.SysUser
 	if sysUser == nil {
 		br.Msg = "请登录"
@@ -1064,6 +1074,28 @@ func (this *CorrelationChartInfoController) Copy() {
 		br.Ret = 408
 		return
 	}
+	var req data_manage.CopyAddChartInfoReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.ChartInfoId <= 0 {
+		br.Msg = "参数有误"
+		br.ErrMsg = fmt.Sprintf("参数有误, ChartInfoId: %d", req.ChartInfoId)
+		return
+	}
+	req.ChartName = strings.TrimSpace(req.ChartName)
+	if req.ChartName == "" {
+		br.Msg = "请输入图表名称"
+		return
+	}
+	if req.ChartClassifyId <= 0 {
+		br.Msg = "请选择图表分类"
+		return
+	}
+
 	deleteCache := true
 	cacheKey := "CACHE_CHART_INFO_ADD_" + strconv.Itoa(sysUser.AdminId)
 	defer func() {
@@ -1077,76 +1109,215 @@ func (this *CorrelationChartInfoController) Copy() {
 		br.ErrMsg = "系统处理中,请稍后重试!" + sysUser.RealName + ";data:" + string(this.Ctx.Input.RequestBody)
 		return
 	}
-	var req data_manage.CopyAddChartInfoReq
-	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
-	if err != nil {
-		br.Msg = "参数解析异常!"
-		br.ErrMsg = "参数解析失败,Err:" + err.Error()
-		return
+
+	chartSource := utils.CHART_SOURCE_CORRELATION
+	// 校验分类、图表名称
+	{
+		var cond string
+		var pars []interface{}
+		switch this.Lang {
+		case utils.EnLangVersion:
+			cond += " AND chart_name_en = ? AND source = ? "
+		default:
+			cond += " AND chart_name = ? AND source = ? "
+		}
+		pars = append(pars, req.ChartName, chartSource)
+		count, e := data_manage.GetChartInfoCountByCondition(cond, pars)
+		if e != nil {
+			br.Msg = "保存失败"
+			br.ErrMsg = fmt.Sprintf("获取同名图表失败, Err: %v", e)
+			return
+		}
+		if count > 0 {
+			br.Msg = "图表名称已存在, 请重新填写"
+			return
+		}
+
+		_, e = data_manage.GetChartClassifyById(req.ChartClassifyId)
+		if e != nil {
+			if e.Error() == utils.ErrNoRow() {
+				br.Msg = "分类不存在"
+				return
+			}
+			br.Msg = "保存失败"
+			br.ErrMsg = fmt.Sprintf("获取图表分类失败, Err: %v", e)
+			return
+		}
 	}
 
-	// 获取原图表信息
-	oldChartInfo, err := data_manage.GetChartInfoById(req.ChartInfoId)
-	if err != nil {
-		br.Msg = "获取原图表信息失败"
-		br.ErrMsg = "获取原图表信息失败,Err:" + err.Error()
+	// 图表信息
+	originChart, e := data_manage.GetChartInfoById(req.ChartInfoId)
+	if e != nil {
+		if e.Error() == utils.ErrNoRow() {
+			br.Msg = "原图表不存在"
+			return
+		}
+		br.Msg = "保存失败"
+		br.ErrMsg = fmt.Sprintf("获取原图表信息失败, Err: %v", e)
 		return
 	}
-	if oldChartInfo.Source == utils.CHART_SOURCE_ROLLING_CORRELATION {
+	if originChart.Source == utils.CHART_SOURCE_ROLLING_CORRELATION {
 		br.Msg = `滚动相关性图不支持另存为`
 		br.IsSendEmail = false
 		return
 	}
 
-	multipleGraphConfigChartMapping, err := data_manage.GetMultipleGraphConfigChartMappingByChartId(req.ChartInfoId)
-	if err != nil && err.Error() != utils.ErrNoRow() {
-		br.Msg = `保存失败`
-		br.ErrMsg = "获取配置与图表的关联关系失败,ERR:" + err.Error()
+	// 相关性图
+	originCorrelate := new(data_manage.ChartInfoCorrelation)
+	if e = originCorrelate.GetItemById(req.ChartInfoId); e != nil {
+		if e.Error() == utils.ErrNoRow() {
+			br.Msg = "原相关性图表不存在"
+			return
+		}
+		br.Msg = "保存失败"
+		br.ErrMsg = fmt.Sprintf("获取原相关性图表信息失败, Err: %v", e)
 		return
 	}
 
-	correlationChart := new(data_manage.ChartInfoCorrelation)
-	if e := correlationChart.GetItemById(req.ChartInfoId); e != nil {
-		br.Msg = "另存为失败"
-		br.ErrMsg = "获取原图表相关性信息失败, Err:" + e.Error()
-		return
-	}
-
-	correlationChartInfoReq := data_manage.CorrelationChartInfoReq{
-		LeadValue:          correlationChart.LeadValue,
-		LeadUnit:           correlationChart.LeadUnit,
-		CalculateValue:     correlationChart.CalculateValue,
-		CalculateUnit:      correlationChart.CalculateUnit,
-		BaseCalculateUnit:  correlationChart.BaseCalculateUnit,
-		BaseCalculateValue: correlationChart.BaseCalculateValue,
-		StartDate:          correlationChart.StartDate.Format(utils.FormatDate),
-		EndDate:            correlationChart.EndDate.Format(utils.FormatDate),
-		EdbInfoIdList: []data_manage.CorrelationChartInfoEdbItemReq{
-			{
-				EdbInfoId: correlationChart.EdbInfoIdFirst,
-				Name:      "",
-				NameEn:    "",
-			}, {
-				EdbInfoId: correlationChart.EdbInfoIdSecond,
-				Name:      "",
-				NameEn:    "",
+	// 普通相关性图表
+	chartInfo := new(data_manage.ChartInfo)
+	if originCorrelate.AnalysisMode != 1 {
+		multipleGraphConfigChartMapping, err := data_manage.GetMultipleGraphConfigChartMappingByChartId(req.ChartInfoId)
+		if err != nil && err.Error() != utils.ErrNoRow() {
+			br.Msg = `保存失败`
+			br.ErrMsg = "获取配置与图表的关联关系失败,ERR:" + err.Error()
+			return
+		}
+
+		correlationChartInfoReq := data_manage.CorrelationChartInfoReq{
+			LeadValue:          originCorrelate.LeadValue,
+			LeadUnit:           originCorrelate.LeadUnit,
+			CalculateValue:     originCorrelate.CalculateValue,
+			CalculateUnit:      originCorrelate.CalculateUnit,
+			BaseCalculateUnit:  originCorrelate.BaseCalculateUnit,
+			BaseCalculateValue: originCorrelate.BaseCalculateValue,
+			StartDate:          originCorrelate.StartDate.Format(utils.FormatDate),
+			EndDate:            originCorrelate.EndDate.Format(utils.FormatDate),
+			EdbInfoIdList: []data_manage.CorrelationChartInfoEdbItemReq{
+				{
+					EdbInfoId: originCorrelate.EdbInfoIdFirst,
+					Name:      "",
+					NameEn:    "",
+				}, {
+					EdbInfoId: originCorrelate.EdbInfoIdSecond,
+					Name:      "",
+					NameEn:    "",
+				},
 			},
-		},
+		}
+
+		newChart, err, errMsg, isSendEmail := correlationServ.CopyChartInfo(multipleGraphConfigChartMapping.MultipleGraphConfigId, req.ChartClassifyId, req.ChartName, correlationChartInfoReq, originChart, sysUser, this.Lang)
+		chartInfo = newChart
+
+		if err != nil {
+			br.Msg = "保存失败"
+			if errMsg != `` {
+				br.Msg = errMsg
+			}
+			br.ErrMsg = err.Error()
+			br.IsSendEmail = isSendEmail
+			return
+		}
 	}
 
-	chartInfo, err, errMsg, isSendEmail := correlationServ.CopyChartInfo(multipleGraphConfigChartMapping.MultipleGraphConfigId, req.ChartClassifyId, req.ChartName, correlationChartInfoReq, oldChartInfo, sysUser, this.Lang)
+	// 多因子相关性图表
+	if originCorrelate.AnalysisMode == 1 {
+		chartInfo.ChartName = req.ChartName
+		chartInfo.ChartNameEn = req.ChartName
+		chartInfo.ChartClassifyId = req.ChartClassifyId
+		chartInfo.SysUserId = sysUser.AdminId
+		chartInfo.SysUserRealName = sysUser.RealName
+		chartInfo.CreateTime = time.Now()
+		chartInfo.ModifyTime = time.Now()
+		timestamp := strconv.FormatInt(time.Now().UnixNano(), 10)
+		chartInfo.UniqueCode = utils.MD5(utils.CHART_PREFIX + "_" + timestamp)
+		chartInfo.ChartType = originChart.ChartType
+		chartInfo.Calendar = originChart.Calendar
+		chartInfo.DateType = originChart.DateType
+		chartInfo.StartDate = originChart.StartDate
+		chartInfo.EndDate = originChart.EndDate
+		chartInfo.SeasonStartDate = originChart.StartDate
+		chartInfo.SeasonEndDate = originChart.EndDate
+		chartInfo.Disabled = originChart.Disabled
+		chartInfo.Source = originChart.Source
+		chartInfo.ChartThemeId = originChart.ChartThemeId
+		chartInfo.ExtraConfig = originChart.ExtraConfig
+		chartInfo.SourcesFrom = originChart.SourcesFrom
+		chartInfo.Instructions = originChart.Instructions
+		chartInfo.MarkersLines = originChart.MarkersLines
+		chartInfo.MarkersAreas = originChart.MarkersAreas
+
+		// 相关性图
+		chartCorrelate := new(data_manage.ChartInfoCorrelation)
+		chartCorrelate.LeadValue = originCorrelate.LeadValue
+		chartCorrelate.LeadUnit = originCorrelate.LeadUnit
+		chartCorrelate.CalculateValue = originCorrelate.CalculateValue
+		chartCorrelate.CalculateUnit = originCorrelate.CalculateUnit
+		chartCorrelate.EdbInfoIdFirst = originCorrelate.EdbInfoIdFirst
+		chartCorrelate.AnalysisMode = 1
+		chartCorrelate.CreateTime = time.Now().Local()
+		chartCorrelate.ModifyTime = time.Now().Local()
+
+		// 图表指标关联
+		edbMappings := make([]*data_manage.ChartEdbMapping, 0)
+		{
+			mappings, e := data_manage.GetChartMappingList(req.ChartInfoId)
+			if e != nil {
+				br.Msg = "保存失败"
+				br.ErrMsg = fmt.Sprintf("获取图表指标关联失败, Err: %v", e)
+				return
+			}
+			for _, v := range mappings {
+				m := new(data_manage.ChartEdbMapping)
+				m.EdbInfoId = v.EdbInfoId
+				edbTimestamp := strconv.FormatInt(time.Now().UnixNano(), 10)
+				m.UniqueCode = utils.MD5(utils.CHART_PREFIX + "_" + edbTimestamp + "_" + strconv.Itoa(v.EdbInfoId))
+				m.IsOrder = true
+				m.IsAxis = 1
+				m.EdbInfoType = 1
+				m.Source = utils.CHART_SOURCE_CORRELATION
+				m.CreateTime = time.Now()
+				m.ModifyTime = time.Now()
+				edbMappings = append(edbMappings, m)
+			}
+		}
 
-	if err != nil {
-		br.Msg = "保存失败"
-		if errMsg != `` {
-			br.Msg = errMsg
+		// 指标系列-图表关联
+		seriesMappings := make([]*data_manage.FactorEdbSeriesChartMapping, 0)
+		{
+			ob := new(data_manage.FactorEdbSeriesChartMapping)
+			cond := fmt.Sprintf(" AND %s = ?", ob.Cols().ChartInfoId)
+			pars := make([]interface{}, 0)
+			pars = append(pars, req.ChartInfoId)
+			mappings, e := ob.GetItemsByCondition(cond, pars, []string{}, "")
+			if e != nil {
+				br.Msg = "保存失败"
+				br.ErrMsg = fmt.Sprintf("获取指标系列-图表关联失败, Err: %v", e)
+				return
+			}
+			for _, v := range mappings {
+				seriesMappings = append(seriesMappings, &data_manage.FactorEdbSeriesChartMapping{
+					FactorEdbSeriesId: v.FactorEdbSeriesId,
+					ChartInfoId:       req.ChartInfoId,
+					EdbInfoId:         v.EdbInfoId,
+					Source:            v.Source,
+					CreateTime:        time.Now().Local(),
+					ModifyTime:        time.Now().Local(),
+				})
+			}
 		}
-		br.ErrMsg = err.Error()
-		br.IsSendEmail = isSendEmail
-		return
+
+		// 新增图表/相关性图表/图表指标关联/指标系列图表关联
+		chartInfoId, e := data_manage.CreateMultiFactorCorrelationChartAndEdb(chartInfo, edbMappings, chartCorrelate, seriesMappings)
+		if e != nil {
+			br.Msg = "保存失败"
+			br.ErrMsg = fmt.Sprintf("新增多因子相关性图表失败, Err: %v", e)
+			return
+		}
+		go data.EsAddOrEditChartInfo(chartInfoId)
 	}
 
-	//新增操作日志
+	// 新增操作日志
 	{
 		chartLog := new(data_manage.ChartInfoLog)
 		chartLog.ChartInfoId = chartInfo.ChartInfoId
@@ -1183,6 +1354,29 @@ func GetChartInfoDetailFromUniqueCode(chartInfo *data_manage.ChartInfoView, isCa
 	edbClassifyPermissionMap := make(map[int]data_manage_permission.EdbClassifyPermission)
 	defer func() {
 		if isOk {
+			// 这里跟当前用户相关的信息重新查询写入resp, 不使用缓存中的
+			{
+				//判断是否加入我的图库
+				var myChartCondition string
+				var myChartPars []interface{}
+				myChartCondition += ` AND a.admin_id=? `
+				myChartPars = append(myChartPars, 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
+				}
+			}
+
 			resp.ChartInfo.HaveOperaAuth = true
 
 			// 指标权限
@@ -1252,33 +1446,12 @@ func GetChartInfoDetailFromUniqueCode(chartInfo *data_manage.ChartInfoView, isCa
 		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")
+				if err != nil || resp == nil {
 					return
 				}
+				isOk = true
+				fmt.Println("source redis")
+				return
 			}
 		}
 	}
@@ -1310,50 +1483,74 @@ func GetChartInfoDetailFromUniqueCode(chartInfo *data_manage.ChartInfoView, isCa
 		errMsg = "获取相关性图表, A指标mapping信息失败, Err:" + e.Error()
 		return
 	}
-	edbInfoMappingB, e := data_manage.GetChartEdbMappingByEdbInfoId(correlationChart.EdbInfoIdSecond)
-	if e != nil {
-		msg = "获取失败"
-		errMsg = "获取相关性图表, B指标mapping信息失败, Err:" + e.Error()
-		return
+	edbInfoMappingB := new(data_manage.ChartEdbInfoMapping)
+	// 非多因子
+	if correlationChart.AnalysisMode != 1 {
+		edbInfoMappingB, e = data_manage.GetChartEdbMappingByEdbInfoId(correlationChart.EdbInfoIdSecond)
+		if e != nil {
+			msg = "获取失败"
+			errMsg = "获取相关性图表, B指标mapping信息失败, Err:" + e.Error()
+			return
+		}
 	}
 
 	var dataResp interface{} // 绘图数据返回(目前是滚动相关性的图)
 	var xEdbIdValue []int
 	var yDataList []data_manage.YData
-	switch chartInfo.Source {
-	case utils.CHART_SOURCE_CORRELATION: // 相关性图
-		moveUnitDays, ok := utils.FrequencyDaysMap[correlationChart.CalculateUnit]
-		if !ok {
-			msg = "错误的分析周期"
-			errMsg = "相关性图表数据有误"
-			return
-		}
-		startDate := time.Now().AddDate(0, 0, -correlationChart.CalculateValue*moveUnitDays).Format(utils.FormatDate)
-		endDate := time.Now().Format(utils.FormatDate)
+	if correlationChart.AnalysisMode != 1 {
+		switch chartInfo.Source {
+		case utils.CHART_SOURCE_CORRELATION: // 相关性图
+			moveUnitDays, ok := utils.FrequencyDaysMap[correlationChart.CalculateUnit]
+			if !ok {
+				msg = "错误的分析周期"
+				errMsg = "相关性图表数据有误"
+				return
+			}
+			startDate := time.Now().AddDate(0, 0, -correlationChart.CalculateValue*moveUnitDays).Format(utils.FormatDate)
+			endDate := time.Now().Format(utils.FormatDate)
 
-		xEdbIdValue, yDataList, e = correlationServ.GetChartDataByEdbInfo(edbInfoMappingA, edbInfoMappingB, correlationChart.LeadValue, correlationChart.LeadUnit, startDate, endDate)
+			xEdbIdValue, yDataList, e = correlationServ.GetChartDataByEdbInfo(edbInfoMappingA, edbInfoMappingB, correlationChart.LeadValue, correlationChart.LeadUnit, startDate, endDate)
+			if e != nil {
+				msg = "获取失败"
+				errMsg = "获取相关性图表, 图表计算值失败, Err:" + e.Error()
+				return
+			}
+		case utils.CHART_SOURCE_ROLLING_CORRELATION: // 滚动相关性图
+			startDate, endDate := utils.GetDateByDateType(correlationChart.DateType, correlationChart.StartDate.Format(utils.FormatDate), correlationChart.EndDate.Format(utils.FormatDate))
+
+			dataResp, e = correlationServ.GetRollingCorrelationChartDataByEdbInfo(edbInfoMappingA, edbInfoMappingB, correlationChart.LeadValue, correlationChart.LeadUnit, correlationChart.CalculateValue, correlationChart.CalculateUnit, startDate, endDate, chartInfo.ChartName, chartInfo.ChartNameEn)
+			if e != nil {
+				msg = "获取失败"
+				errMsg = "获取滚动相关性图表, 图表计算值失败, Err:" + e.Error()
+				return
+			}
+		}
+	} else {
+		xEdbIdValue, yDataList, e = correlationServ.GetFactorChartDataByChartId(chartInfoId, chartInfo.ExtraConfig)
 		if e != nil {
 			msg = "获取失败"
 			errMsg = "获取相关性图表, 图表计算值失败, Err:" + e.Error()
 			return
 		}
-	case utils.CHART_SOURCE_ROLLING_CORRELATION: // 滚动相关性图
-		startDate, endDate := utils.GetDateByDateType(correlationChart.DateType, correlationChart.StartDate.Format(utils.FormatDate), correlationChart.EndDate.Format(utils.FormatDate))
+	}
 
-		dataResp, e = correlationServ.GetRollingCorrelationChartDataByEdbInfo(edbInfoMappingA, edbInfoMappingB, correlationChart.LeadValue, correlationChart.LeadUnit, correlationChart.CalculateValue, correlationChart.CalculateUnit, startDate, endDate, chartInfo.ChartName, chartInfo.ChartNameEn)
+	// 完善指标信息
+	edbList := make([]*data_manage.ChartEdbInfoMapping, 0)
+	if correlationChart.AnalysisMode != 1 {
+		edbList, e = correlationServ.GetChartEdbInfoFormat(chartInfo.ChartInfoId, edbInfoMappingA, edbInfoMappingB)
 		if e != nil {
 			msg = "获取失败"
-			errMsg = "获取滚动相关性图表, 图表计算值失败, Err:" + e.Error()
+			errMsg = "获取相关性图表, 完善指标信息失败, Err:" + e.Error()
+			return
+		}
+	} else {
+		// 多因子指标, 获取图表引用到的系列指标(去重后)
+		edbList, e = data_manage.GetChartEdbMappingListByIdList([]int{chartInfoId})
+		if e != nil {
+			msg = "获取失败"
+			errMsg = "获取图表引用系列指标失败, Err:" + e.Error()
 			return
 		}
-	}
-
-	// 完善指标信息
-	edbList, e := correlationServ.GetChartEdbInfoFormat(chartInfo.ChartInfoId, edbInfoMappingA, edbInfoMappingB)
-	if e != nil {
-		msg = "获取失败"
-		errMsg = "获取相关性图表, 完善指标信息失败, Err:" + e.Error()
-		return
 	}
 	correlationInfo := new(data_manage.CorrelationInfo)
 	correlationInfo.LeadValue = correlationChart.LeadValue
@@ -1365,6 +1562,7 @@ func GetChartInfoDetailFromUniqueCode(chartInfo *data_manage.ChartInfoView, isCa
 	correlationInfo.LeadValue = correlationChart.LeadValue
 	correlationInfo.EdbInfoIdFirst = correlationChart.EdbInfoIdFirst
 	correlationInfo.EdbInfoIdSecond = correlationChart.EdbInfoIdSecond
+	correlationInfo.AnalysisMode = correlationChart.AnalysisMode
 
 	if chartInfoId > 0 && chartInfo != nil {
 		//判断是否加入我的图库

+ 27 - 25
controllers/data_manage/cross_variety/chart_info.go

@@ -1525,6 +1525,29 @@ func GetChartInfoDetailFromUniqueCode(chartInfo *data_manage.ChartInfoView, isCa
 	edbClassifyPermissionMap := make(map[int]data_manage_permission.EdbClassifyPermission)
 	defer func() {
 		if isOk {
+			// 这里跟当前用户相关的信息重新查询写入resp, 不使用缓存中的
+			{
+				//判断是否加入我的图库
+				var myChartCondition string
+				var myChartPars []interface{}
+				myChartCondition += ` AND a.admin_id=? `
+				myChartPars = append(myChartPars, 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
+				}
+			}
+
 			resp.ChartInfo.HaveOperaAuth = true
 
 			// 指标权限
@@ -1594,33 +1617,12 @@ func GetChartInfoDetailFromUniqueCode(chartInfo *data_manage.ChartInfoView, isCa
 		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")
+				if err != nil || resp == nil {
 					return
 				}
+				isOk = true
+				fmt.Println("source redis")
+				return
 			}
 		}
 	}

+ 49 - 59
controllers/data_manage/edb_info.go

@@ -2,6 +2,7 @@ package data_manage
 
 import (
 	"encoding/json"
+	"eta/eta_mobile/cache"
 	"eta/eta_mobile/controllers"
 	"eta/eta_mobile/models"
 	"eta/eta_mobile/models/company"
@@ -1723,6 +1724,37 @@ func (this *EdbInfoController) EdbInfoSearch() {
 				searchItem.Unit = "%"
 				searchItem.EdbName = indexInfo.IndexName
 			}
+		} else if source == utils.DATA_SOURCE_BUSINESS { //自有数据
+			indexObj := data_manage.BaseFromBusinessIndex{}
+			indexInfo, err := indexObj.GetDetailByEdbCode(edbCode)
+			if err != nil && err.Error() != utils.ErrNoRow() {
+				br.Msg = "获取失败"
+				br.ErrMsg = "获取自有数据指标信息失败,Err:" + err.Error()
+				return
+			}
+
+			//obj := mgo.BaseFromBusinessData{}
+			//tmpDataList, err := obj.GetLimitDataList(bson.M{"index_code": edbCode}, utils.EDB_DATA_LIMIT, []string{"-data_time"})
+			_, tmpDataList, err := data.GetPageBaseBusinessIndexData(edbCode, 1, utils.EDB_DATA_LIMIT)
+			if err != nil && err.Error() != utils.ErrNoRow() {
+				br.Msg = "获取失败"
+				br.ErrMsg = "获取自有数据已存在信息失败,Err:" + err.Error()
+				return
+			}
+			dataItems := make([]*data_manage.EdbInfoSearchData, 0)
+			for _, v := range tmpDataList {
+				dataItems = append(dataItems, &data_manage.EdbInfoSearchData{
+					DataTime: v.DataTime,
+					Value:    v.Value,
+				})
+			}
+			searchItem.EdbCode = edbCode
+			searchItem.DataList = dataItems
+			searchItem.StartDate = indexInfo.StartDate.Format(utils.FormatDate)
+			searchItem.EndDate = indexInfo.EndDate.Format(utils.FormatDate)
+			searchItem.Frequency = indexInfo.Frequency
+			searchItem.Unit = indexInfo.Unit
+			searchItem.EdbName = indexInfo.IndexName
 		} else {
 			// 代码中没有的来源那么从edb_source中找是否有对应的
 			sourceItem := data_manage.EdbSourceIdMap[source]
@@ -2094,64 +2126,14 @@ func (this *EdbInfoController) EdbInfoList() {
 
 	// 如果有数据权限,那么就去获取指标数据
 	if edbInfoItem.HaveOperaAuth {
-		var dataCondition string
-		var dataPars []interface{}
-
-		dataCondition += ` AND edb_info_id=? `
-		dataPars = append(dataPars, edbInfoItem.EdbInfoId)
-
-		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
+		dataCount, dataList, err := data.GetPageData(edbInfoItem.EdbInfoId, edbInfoItem.Source, edbInfoItem.SubSource, "", startSize, pageSize)
+		if err != nil && err.Error() != utils.ErrNoRow() {
+			br.Msg = "获取指标信息失败"
+			br.ErrMsg = "获取指标数据总数失败,Err:" + err.Error()
+			return
 		}
+		page = paging.GetPaging(currentIndex, pageSize, dataCount)
+		edbInfoItem.DataList = dataList
 	}
 
 	// 获取指标插入配置
@@ -2453,7 +2435,7 @@ func (this *EdbInfoController) EdbInfoEdit() {
 		edbInfo.Frequency = req.Frequency
 		edbInfo.Unit = req.Unit
 		edbInfo.ClassifyId = req.ClassifyId
-		updateCols = append(updateCols, "EdbNameEn", "EdbNameSource", "Frequency", "UnitEn", "ClassifyId")
+		updateCols = append(updateCols, "EdbName", "EdbNameSource", "Frequency", "Unit", "ClassifyId")
 	}
 	pars = append(pars, req.EdbName)
 
@@ -3881,6 +3863,8 @@ func (this *ChartInfoController) EdbInfoReplace() {
 	} else {
 		//msgContent = oldEdbInfo.EdbName + "指标替换" + newEdbInfo.EdbName + "指标,全部替换成功,涉及" + strconv.Itoa(replaceChartTotal) + "张图表,\n\n" + strconv.Itoa(replaceCalculateTotal) + "个计算指标"
 		isFail = false
+		//加入到缓存队列中处理
+		go cache.AddReplaceEdbInfo(oldEdbInfo, newEdbInfo)
 	}
 
 	// 添加站内信息
@@ -5726,11 +5710,14 @@ func (this *EdbInfoController) EdbInfoBatchAdd() {
 			edbInfoItem.SourceName = "ths"
 			edbInfoItem.EdbCode = utils.ThsDs + v.StockCode + v.EdbCode
 		}
-		edbInfoItem.SubSource = 1
+		edbInfoItem.SubSource = utils.DATA_SUB_SOURCE_DATE
 		edbInfoItem.SubSourceName = "日期序列"
 		edbInfoItem.EdbName = v.EdbName
+		edbInfoItem.EdbNameSource = v.EdbName
+		edbInfoItem.EdbNameEn = v.EdbName
 		edbInfoItem.Frequency = v.Frequency
 		edbInfoItem.Unit = v.Unit
+		edbInfoItem.UnitEn = v.Unit
 		edbInfoItem.ClassifyId = v.ClassifyId
 		edbInfoItem.SysUserId = sysUser.AdminId
 		edbInfoItem.SysUserRealName = sysUser.RealName
@@ -6313,8 +6300,11 @@ func (this *EdbInfoController) SmmEdbInfoBatchAdd() {
 		edbInfoItem.SubSource = 0
 		edbInfoItem.SubSourceName = ""
 		edbInfoItem.EdbName = v.EdbName
+		edbInfoItem.EdbNameSource = v.EdbName
+		edbInfoItem.EdbNameEn = v.EdbName
 		edbInfoItem.Frequency = v.Frequency
 		edbInfoItem.Unit = v.Unit
+		edbInfoItem.UnitEn = v.Unit
 		edbInfoItem.ClassifyId = v.ClassifyId
 		edbInfoItem.SysUserId = sysUser.AdminId
 		edbInfoItem.SysUserRealName = sysUser.RealName

+ 8 - 4
controllers/data_manage/edb_info_calculate.go

@@ -1456,9 +1456,6 @@ func (this *EdbInfoController) QueryEdbDataTable() {
 		br.ErrMsg = "获取指标信息失败,err:" + err.Error()
 		return
 	}
-
-	tableName := data_manage.GetEdbDataTableName(edbInfo.Source, edbInfo.SubSource)
-
 	columnList := []map[string]string{
 		{
 			"edb_code": "指标code",
@@ -1471,7 +1468,14 @@ func (this *EdbInfoController) QueryEdbDataTable() {
 		},
 	}
 
-	templateStr := fmt.Sprintf("sql1 = f\"\"\"SELECT data_time,`value` FROM %s WHERE edb_code = '%s' ORDER BY data_time DESC;\"\"\"\nraw = pandas_fetch_all(sql1, db)", tableName, edbInfo.EdbCode)
+	tableName := data_manage.GetEdbDataTableName(edbInfo.Source, edbInfo.SubSource)
+
+	var templateStr string
+	if edbInfo.Source == utils.DATA_SOURCE_BUSINESS && utils.UseMongo {
+		templateStr = fmt.Sprintf("# 查询条件\nquery = {\"edb_code\": \"%s\"}\n# 排序\nsort = [(\"data_time\", -1)]  # -1 表示降序排列,对应 SQL 的 DESC\nprojection = {\"data_time\": 1, \"value\": 1, \"_id\": 0}  # 只选择data_time和value字段,忽略_id字段\n# 使用 find() 方法获取数据,然后使用 aggregate() 转换为列表\nraw_data = list(collection.find(query, projection).sort(sort))\n# 将结果转换为 DataFrame\nraw = pd.DataFrame(raw_data)\n# 转换data_time字段为本地时区时间\nraw['data_time'] = raw['data_time'].apply(lambda x: x.replace(tzinfo=utc_tz)).dt.tz_convert(local_tz).dt.strftime('%s')", edbInfo.EdbCode, "%Y-%m-%d")
+	} else {
+		templateStr = fmt.Sprintf("sql1 = f\"\"\"SELECT data_time,`value` FROM %s WHERE edb_code = '%s' ORDER BY data_time DESC;\"\"\"\nraw = pandas_fetch_all(sql1, db)", tableName, edbInfo.EdbCode)
+	}
 	info := data_manage.TableInfoResp{
 		ColumnList:  columnList,
 		TableName:   tableName,

+ 241 - 0
controllers/data_manage/excel/balance_table.go

@@ -0,0 +1,241 @@
+package excel
+
+import (
+	"encoding/json"
+	"errors"
+	"eta/eta_mobile/models"
+	"eta/eta_mobile/models/data_manage"
+	"eta/eta_mobile/models/data_manage/excel"
+	"eta/eta_mobile/models/data_manage/excel/request"
+	"eta/eta_mobile/models/data_manage/excel/response"
+	"eta/eta_mobile/services/data"
+	"eta/eta_mobile/services/data/data_manage_permission"
+	excelService "eta/eta_mobile/services/data/excel"
+	"eta/eta_mobile/utils"
+	"fmt"
+	"time"
+)
+
+// DeleteBalanceChart
+// @Title 删除平衡表图表
+// @Description 删除平衡表图表
+// @Param	request	body data_manage.DeleteChartClassifyReq true "type json string"
+// @Success 200 Ret=200 删除成功
+// @router /excel_info/balance/chart_del [post]
+func (c *ExcelInfoController) DeleteBalanceChart() {
+	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
+	}
+	//删除图表
+	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
+		}
+
+		// 操作权限校验, 增加协作人判断
+		{
+			// 获取表格信息
+			excelInfo, e := excel.GetExcelInfoByChartInfoId(req.ChartInfoId)
+			if e != nil {
+				br.Msg = "获取ETA表格失败"
+				return
+			}
+			checkExcelInfo := excelInfo
+			if excelInfo.Source == utils.BALANCE_TABLE {
+				checkExcelInfoId := excelInfo.ExcelInfoId
+				if excelInfo.BalanceType == 1 {
+					checkExcelInfoId = excelInfo.RelExcelInfoId
+				} else {
+					if excelInfo.ParentId > 0 {
+						checkExcelInfoId = excelInfo.ParentId
+					}
+				}
+				if checkExcelInfoId != excelInfo.ExcelInfoId {
+					checkExcelInfo, e = excel.GetExcelInfoById(checkExcelInfoId)
+					if e != nil {
+						br.Msg = "获取平衡表格信息失败"
+						br.ErrMsg = "获取平衡表格信息失败,Err:" + e.Error()
+						return
+					}
+				}
+			}
+			// 数据权限
+			haveOperaAuth, e := data_manage_permission.CheckExcelPermissionByExcelInfoId(checkExcelInfo.ExcelInfoId, checkExcelInfo.ExcelClassifyId, checkExcelInfo.IsJoinPermission, c.SysUser.AdminId)
+			if e != nil {
+				br.Msg = "获取ETA表格权限失败"
+				br.ErrMsg = "获取表格权限信息失败,Err" + e.Error()
+				return
+			}
+
+			button := excelService.GetBalanceExcelInfoOpButton(sysUser.AdminId, checkExcelInfo.SysUserId, haveOperaAuth, checkExcelInfo.ExcelInfoId)
+			if !button.OpButton {
+				br.Msg = "无操作权限"
+				br.IsSendEmail = false
+				return
+			}
+		}
+
+		// 获取引用该图表的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
+		}
+		myIds := make([]int, 0)
+		for _, m := range myCharts {
+			myIds = append(myIds, m.MyChartId)
+		}
+
+		//删除图表及关联指标
+		e = excel.DeleteBalanceExcelChartInfoAndData(req.ChartInfoId)
+		if e != nil {
+			br.Msg = "删除失败"
+			br.ErrMsg = "删除失败,Err:" + e.Error()
+			return
+		}
+		//删除ES
+		{
+			go data.EsDeleteChartInfo(req.ChartInfoId)
+			// 删除MY ETA 图表 es数据
+			//go data.EsDeleteMyChartInfoByChartInfoId(req.ChartInfoId)
+			go data.EsDeleteMyChartInfoByMyChartIds(myIds)
+		}
+
+		//新增操作日志
+		{
+			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.IsAddLog = true
+}
+
+func refreshBalanceTable(excelDetail response.ExcelInfoDetail, lang string) (err error) {
+	edbInfoIds := make([]int, 0)
+	edbInfoIdExist := make(map[int]bool)
+	if excelDetail.ParentId > 0 {
+		newResult := excelDetail.TableData.(request.MixedTableReq)
+		newData := newResult.Data
+		if len(newData) > 0 {
+			for _, t := range newData {
+				for _, v := range t {
+					if v.EdbInfoId > 0 && !edbInfoIdExist[v.EdbInfoId] {
+						edbInfoIdExist[v.EdbInfoId] = true
+						edbInfoIds = append(edbInfoIds, v.EdbInfoId)
+					}
+				}
+			}
+		}
+
+		// 清除缓存
+		key := utils.HZ_CHART_LIB_EXCEL_TABLE_DETAIL + ":" + excelDetail.UniqueCode
+		if utils.Re == nil {
+			_ = utils.Rc.Delete(key)
+		}
+	} else {
+		//查询父表和子表
+		cCondition := " AND parent_id = ? AND balance_type=0"
+		var cPars []interface{}
+		cPars = append(cPars, excelDetail.ExcelInfoId)
+		childList, e := excel.GetExcelInfoListByCondition(cCondition, cPars)
+		if e != nil {
+			err = fmt.Errorf("获取子表失败 %s", err.Error())
+			return
+		}
+		// 遍历
+		for _, child := range childList {
+			var result request.MixedTableReq
+			err = json.Unmarshal([]byte(child.Content), &result)
+			if err != nil {
+				err = errors.New("表格json转结构体失败,Err:" + err.Error())
+				return
+			}
+			var newData [][]request.MixedTableCellDataReq
+			newData, err, _ = excelService.GetMixedTableCellData(result, lang)
+			if err != nil {
+				return
+			}
+
+			if len(newData) > 0 {
+				for _, t := range newData {
+					for _, v := range t {
+						if v.EdbInfoId > 0 && !edbInfoIdExist[v.EdbInfoId] {
+							edbInfoIdExist[v.EdbInfoId] = true
+							edbInfoIds = append(edbInfoIds, v.EdbInfoId)
+						}
+					}
+				}
+			}
+
+			// 清除缓存
+			key := utils.HZ_CHART_LIB_EXCEL_TABLE_DETAIL + ":" + child.UniqueCode
+			if utils.Re == nil {
+				_ = utils.Rc.Delete(key)
+			}
+		}
+	}
+
+	if len(edbInfoIds) > 0 {
+		err, _ = data.EdbInfoRefreshAllFromBaseV3(edbInfoIds, false, true, false)
+		if err != nil {
+			err = fmt.Errorf("刷新混合表格数据失败, Err: " + err.Error())
+			return
+		}
+	}
+	return
+}

+ 144 - 15
controllers/data_manage/excel/excel_info.go

@@ -229,6 +229,7 @@ func (c *ExcelInfoController) Add() {
 		IsDelete:        0,
 		ModifyTime:      time.Now(),
 		CreateTime:      time.Now(),
+		SourcesFrom:     req.SourcesFrom,
 	}
 
 	excelEdbMappingList := make([]*excel3.ExcelEdbMapping, 0)
@@ -732,13 +733,14 @@ func (c *ExcelInfoController) Edit() {
 	excelInfo.ExcelClassifyId = req.ExcelClassifyId
 	excelInfo.ExcelImage = req.ExcelImage
 	excelInfo.Content = content
+	excelInfo.SourcesFrom = req.SourcesFrom
 
 	// 自动保存时不会传缩略图,也就不更新这个字段
 	var updateExcelInfoParams []string
 	if req.ExcelImage != "" {
-		updateExcelInfoParams = []string{"ModifyTime", "ExcelName", "ExcelType", "ExcelClassifyId", "ExcelImage", "Content"}
+		updateExcelInfoParams = []string{"ModifyTime", "ExcelName", "ExcelType", "ExcelClassifyId", "ExcelImage", "Content", "SourcesFrom"}
 	} else {
-		updateExcelInfoParams = []string{"ModifyTime", "ExcelName", "ExcelType", "ExcelClassifyId", "Content"}
+		updateExcelInfoParams = []string{"ModifyTime", "ExcelName", "ExcelType", "ExcelClassifyId", "Content", "SourcesFrom"}
 	}
 
 	excelEdbMappingList := make([]*excel3.ExcelEdbMapping, 0)
@@ -1268,6 +1270,7 @@ func (c *ExcelInfoController) GetExcelTableData() {
 	}
 
 	var tableData excel.TableData
+	var excelSource, excelSourceEn string
 	switch excelInfo.Source {
 	case utils.EXCEL_DEFAULT:
 		luckySheetData, err := excel.GetLuckySheetData(excelInfo.Content)
@@ -1302,6 +1305,14 @@ func (c *ExcelInfoController) GetExcelTableData() {
 			br.ErrMsg = "转换成table失败,Err:" + err.Error()
 			return
 		}
+		sourceNameList, sourceNameEnList, err := excel2.GetEdbSourceByEdbInfoIdList(result.EdbInfoIdList)
+		if err != nil {
+			br.Msg = "自定义表格数据获取失败"
+			br.ErrMsg = "自定义表格数据获取失败,Err:" + err.Error()
+			return
+		}
+		excelSource = strings.Join(sourceNameList, ",")
+		excelSourceEn = strings.Join(sourceNameEnList, ",")
 	case utils.MIXED_TABLE:
 		var result request.MixedTableReq
 		err = json.Unmarshal([]byte(excelInfo.Content), &result)
@@ -1319,12 +1330,32 @@ func (c *ExcelInfoController) GetExcelTableData() {
 			br.ErrMsg = "获取最新的数据失败,Err:" + err.Error()
 			return
 		}
-		tableData, err = excel.GetTableDataByMixedTableData(newResult)
+		tableData, err = excel.GetTableDataByMixedTableData(newResult, true)
 		if err != nil {
 			br.Msg = "获取失败"
 			br.ErrMsg = "转换成table失败,Err:" + err.Error()
 			return
 		}
+		edbInfoIds := make([]int, 0)
+		edbInfoIdExist := make(map[int]bool)
+		if len(newResult) > 0 {
+			for _, t := range newResult {
+				for _, v := range t {
+					if v.EdbInfoId > 0 && !edbInfoIdExist[v.EdbInfoId] {
+						edbInfoIdExist[v.EdbInfoId] = true
+						edbInfoIds = append(edbInfoIds, v.EdbInfoId)
+					}
+				}
+			}
+		}
+		sourceNameList, sourceNameEnList, err := excel2.GetEdbSourceByEdbInfoIdList(edbInfoIds)
+		if err != nil {
+			br.Msg = "自定义表格数据获取失败"
+			br.ErrMsg = "自定义表格数据获取失败,Err:" + err.Error()
+			return
+		}
+		excelSource = strings.Join(sourceNameList, ",")
+		excelSourceEn = strings.Join(sourceNameEnList, ",")
 
 	}
 
@@ -1347,11 +1378,14 @@ func (c *ExcelInfoController) GetExcelTableData() {
 	}
 
 	resp := response.ExcelTableDetailResp{
-		UniqueCode: excelInfo.UniqueCode,
-		ExcelImage: excelInfo.ExcelImage,
-		ExcelName:  excelInfo.ExcelName,
-		TableInfo:  tableData,
-		Config:     config,
+		UniqueCode:    excelInfo.UniqueCode,
+		ExcelImage:    excelInfo.ExcelImage,
+		ExcelName:     excelInfo.ExcelName,
+		TableInfo:     tableData,
+		Config:        config,
+		SourcesFrom:   excelInfo.SourcesFrom,
+		ExcelSource:   excelSource,
+		ExcelSourceEn: excelSourceEn,
 	}
 	br.Ret = 200
 	br.Success = true
@@ -1532,12 +1566,23 @@ func (c *ExcelInfoController) GetFirstEdbData() {
 		}
 	}
 
+	sourceNameList, sourceNameEnList, err := excel2.GetEdbSourceByEdbInfoIdList([]int{edbInfoId})
+	if err != nil {
+		br.Msg = "自定义表格数据获取失败"
+		br.ErrMsg = "自定义表格数据获取失败,Err:" + err.Error()
+		return
+	}
+	excelSource := strings.Join(sourceNameList, ",")
+	excelSourceEn := strings.Join(sourceNameEnList, ",")
+
 	br.Ret = 200
 	br.Success = true
 	br.Msg = "获取成功"
 	br.Data = response.TableDataItem{
-		EdbInfoId: edbInfoId,
-		Data:      dataList,
+		EdbInfoId:     edbInfoId,
+		Data:          dataList,
+		ExcelSource:   excelSource,
+		ExcelSourceEn: excelSourceEn,
 	}
 }
 
@@ -1600,12 +1645,23 @@ func (c *ExcelInfoController) GetOtherEdbData() {
 		}
 	}
 
+	sourceNameList, sourceNameEnList, err := excel2.GetEdbSourceByEdbInfoIdList([]int{req.EdbInfoId})
+	if err != nil {
+		br.Msg = "自定义表格数据获取失败"
+		br.ErrMsg = "自定义表格数据获取失败,Err:" + err.Error()
+		return
+	}
+	excelSource := strings.Join(sourceNameList, ",")
+	excelSourceEn := strings.Join(sourceNameEnList, ",")
+
 	br.Ret = 200
 	br.Success = true
 	br.Msg = "获取成功"
 	br.Data = response.TableDataItem{
-		EdbInfoId: req.EdbInfoId,
-		Data:      dataList,
+		EdbInfoId:     req.EdbInfoId,
+		Data:          dataList,
+		ExcelSource:   excelSource,
+		ExcelSourceEn: excelSourceEn,
 	}
 }
 
@@ -1915,13 +1971,25 @@ func (c *ExcelInfoController) Refresh() {
 	}
 
 	excelInfoId, _ := c.GetInt("ExcelInfoId")
-	if excelInfoId <= 0 {
+	chartInfoId, _ := c.GetInt("ChartInfoId")
+	if excelInfoId <= 0 && chartInfoId <= 0 {
 		br.Msg = "请选择表格"
 		br.ErrMsg = "ExcelInfoId未传"
 		br.IsSendEmail = false
 		return
 	}
 
+	// todo 如果请求入参是chart_info_id,则需要获取excel_info_id
+	if chartInfoId > 0 && excelInfoId == 0 {
+		excelInfo, err := excel3.GetExcelInfoByChartInfoId(chartInfoId)
+		if err != nil {
+			br.Msg = "请选择表格"
+			br.ErrMsg = "未找到对应的表格"
+			br.IsSendEmail = false
+			return
+		}
+		excelInfoId = excelInfo.ExcelInfoId
+	}
 	// 获取数据详情
 	excelDetail, errMsg, err := excel2.GetExcelDetailInfoByExcelInfoId(excelInfoId, c.SysUser.AdminId, c.Lang)
 	if err != nil {
@@ -1932,7 +2000,10 @@ func (c *ExcelInfoController) Refresh() {
 
 	// 操作权限校验
 	{
-		button := excel2.GetExcelInfoOpButton(sysUser, excelDetail.SysUserId, excelDetail.Source, excelDetail.HaveOperaAuth)
+		button := excelDetail.Button
+		if excelDetail.Source != utils.BALANCE_TABLE {
+			button = excel2.GetExcelInfoOpButton(sysUser, excelDetail.SysUserId, excelDetail.Source, excelDetail.HaveOperaAuth)
+		}
 		if !button.RefreshButton {
 			br.Msg = "无操作权限"
 			br.IsSendEmail = false
@@ -1968,6 +2039,7 @@ func (c *ExcelInfoController) Refresh() {
 
 	// 数据刷新-混合表格
 	if excelDetail.Source == utils.MIXED_TABLE {
+		// todo 刷新动态表的所有子表中关联的指标数据
 		jsonByte, e := json.Marshal(excelDetail.TableData)
 		if e != nil {
 			br.Msg = "刷新失败"
@@ -2002,6 +2074,15 @@ func (c *ExcelInfoController) Refresh() {
 		}
 	}
 
+	if excelDetail.Source == utils.BALANCE_TABLE {
+		err = refreshBalanceTable(excelDetail, c.Lang)
+		if err != nil {
+			br.Msg = "刷新失败"
+			br.ErrMsg = "刷新失败,Err:" + err.Error()
+			return
+		}
+	}
+
 	// 清除缓存
 	key := utils.HZ_CHART_LIB_EXCEL_TABLE_DETAIL + ":" + excelDetail.UniqueCode
 	if utils.Re == nil {
@@ -2108,7 +2189,7 @@ func (c *ExcelInfoController) Download() {
 			br.ErrMsg = "获取最新的数据失败,Err:" + err.Error()
 			return
 		}
-		tableData, err = excel.GetTableDataByMixedTableData(newResult)
+		tableData, err = excel.GetTableDataByMixedTableData(newResult, false)
 		if err != nil {
 			br.Msg = "获取失败"
 			br.ErrMsg = "转换成table失败,Err:" + err.Error()
@@ -2502,3 +2583,51 @@ func (c *ExcelInfoController) GetBatchChartRefreshResult() {
 	br.Ret = 200
 	br.Success = true
 }
+
+// GetBatchChartRefreshResult
+// @Title 获取批量刷新表格结果
+// @Description 获取批量刷新表格结果
+// @Param   EdbInfoId   query   int  true       "edb id"
+// @Success Ret=200 刷新成功
+// @router /excel_info/get_edb_source [get]
+func (c *ExcelInfoController) GetEdbSource() {
+	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
+	}
+	edbInfoId, _ := c.GetInt("EdbInfoId")
+	if edbInfoId <= 0 {
+		br.Msg = "请选择指标"
+		br.ErrMsg = "请选择指标"
+		br.IsSendEmail = false
+		return
+	}
+	sourceNameList, sourceNameEnList, err := excel2.GetEdbSourceByEdbInfoIdList([]int{edbInfoId})
+	if err != nil {
+		br.Msg = "自定义表格数据获取失败"
+		br.ErrMsg = "自定义表格数据获取失败,Err:" + err.Error()
+		return
+	}
+	excelSource := strings.Join(sourceNameList, ",")
+	excelSourceEn := strings.Join(sourceNameEnList, ",")
+
+	var resp struct {
+		ExcelSource   string `description:"表格来源"`
+		ExcelSourceEn string `description:"表格来源(英文)"`
+	}
+
+	resp.ExcelSource = excelSource
+	resp.ExcelSourceEn = excelSourceEn
+
+	br.Data = resp
+	br.Ret = 200
+	br.Success = true
+}

+ 27 - 25
controllers/data_manage/future_good/future_good_chart_info.go

@@ -1500,6 +1500,29 @@ func GetChartInfoDetailFromUniqueCode(chartInfo *data_manage.ChartInfoView, isCa
 	edbClassifyPermissionMap := make(map[int]data_manage_permission.EdbClassifyPermission)
 	defer func() {
 		if isOk {
+			// 这里跟当前用户相关的信息重新查询写入resp, 不使用缓存中的
+			{
+				//判断是否加入我的图库
+				var myChartCondition string
+				var myChartPars []interface{}
+				myChartCondition += ` AND a.admin_id=? `
+				myChartPars = append(myChartPars, 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
+				}
+			}
+
 			resp.ChartInfo.HaveOperaAuth = true
 
 			// 指标权限
@@ -1569,33 +1592,12 @@ func GetChartInfoDetailFromUniqueCode(chartInfo *data_manage.ChartInfoView, isCa
 		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")
+				if err != nil || resp == nil {
 					return
 				}
+				isOk = true
+				fmt.Println("source redis")
+				return
 			}
 		}
 	}

+ 27 - 25
controllers/data_manage/future_good/future_good_profit_chart_info.go

@@ -1113,6 +1113,29 @@ func GetFutureGoodProfitChartInfoDetailFromUniqueCode(chartInfo *data_manage.Cha
 	edbClassifyPermissionMap := make(map[int]data_manage_permission.EdbClassifyPermission)
 	defer func() {
 		if isOk {
+			// 这里跟当前用户相关的信息重新查询写入resp, 不使用缓存中的
+			{
+				//判断是否加入我的图库
+				var myChartCondition string
+				var myChartPars []interface{}
+				myChartCondition += ` AND a.admin_id=? `
+				myChartPars = append(myChartPars, 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
+				}
+			}
+
 			resp.ChartInfo.HaveOperaAuth = true
 
 			// 指标权限
@@ -1182,33 +1205,12 @@ func GetFutureGoodProfitChartInfoDetailFromUniqueCode(chartInfo *data_manage.Cha
 		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")
+				if err != nil || resp == nil {
 					return
 				}
+				isOk = true
+				fmt.Println("source redis")
+				return
 			}
 		}
 	}

+ 27 - 25
controllers/data_manage/line_equation/line_chart_info.go

@@ -1207,6 +1207,29 @@ func GetChartInfoDetailFromUniqueCode(chartInfo *data_manage.ChartInfoView, isCa
 	edbClassifyPermissionMap := make(map[int]data_manage_permission.EdbClassifyPermission)
 	defer func() {
 		if isOk {
+			// 这里跟当前用户相关的信息重新查询写入resp, 不使用缓存中的
+			{
+				//判断是否加入我的图库
+				var myChartCondition string
+				var myChartPars []interface{}
+				myChartCondition += ` AND a.admin_id=? `
+				myChartPars = append(myChartPars, 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
+				}
+			}
+
 			resp.ChartInfo.HaveOperaAuth = true
 
 			// 指标权限
@@ -1276,33 +1299,12 @@ func GetChartInfoDetailFromUniqueCode(chartInfo *data_manage.ChartInfoView, isCa
 		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")
+				if err != nil || resp == nil {
 					return
 				}
+				isOk = true
+				fmt.Println("source redis")
+				return
 			}
 		}
 	}

+ 27 - 25
controllers/data_manage/line_feature/chart_info.go

@@ -2304,6 +2304,29 @@ func GetChartInfoDetailFromUniqueCode(chartInfo *data_manage.ChartInfoView, isCa
 	edbClassifyPermissionMap := make(map[int]data_manage_permission.EdbClassifyPermission)
 	defer func() {
 		if isOk {
+			// 这里跟当前用户相关的信息重新查询写入resp, 不使用缓存中的
+			{
+				//判断是否加入我的图库
+				var myChartCondition string
+				var myChartPars []interface{}
+				myChartCondition += ` AND a.admin_id=? `
+				myChartPars = append(myChartPars, 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
+				}
+			}
+
 			resp.ChartInfo.HaveOperaAuth = true
 
 			// 指标权限
@@ -2373,33 +2396,12 @@ func GetChartInfoDetailFromUniqueCode(chartInfo *data_manage.ChartInfoView, isCa
 		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")
+				if err != nil || resp == nil {
 					return
 				}
+				isOk = true
+				fmt.Println("source redis")
+				return
 			}
 		}
 	}

+ 2 - 0
controllers/data_manage/my_chart.go

@@ -1357,6 +1357,8 @@ func (this *MyChartController) MyChartList() {
 			// 数据权限
 			if currClassify, ok := classifyMap[chartViewInfo.ChartClassifyId]; ok {
 				list[i].HaveOperaAuth = data_manage_permission.CheckChartPermissionByPermissionIdList(chartViewInfo.IsJoinPermission, currClassify.IsJoinPermission, chartViewInfo.ChartInfoId, chartViewInfo.ChartClassifyId, permissionChartIdList, permissionClassifyIdList)
+			} else if chartViewInfo.ChartClassifyId == 0 {
+				list[i].HaveOperaAuth = data_manage_permission.CheckChartPermissionByPermissionIdList(chartViewInfo.IsJoinPermission, 0, chartViewInfo.ChartInfoId, chartViewInfo.ChartClassifyId, permissionChartIdList, permissionClassifyIdList)
 			}
 		}
 

+ 3 - 33
controllers/data_manage/predict_edb_info.go

@@ -318,25 +318,13 @@ func (this *PredictEdbInfoController) List() {
 
 		//获取指标数据(实际已生成)
 		{
-			var dataCondition string
-			var dataPars []interface{}
-
-			dataCondition += ` AND edb_info_id=? `
-			dataPars = append(dataPars, sourceEdbInfoItem.EdbInfoId)
-
-			dataCount, err := data_manage.GetEdbDataCountByCondition(dataCondition, dataPars, sourceEdbInfoItem.Source, sourceEdbInfoItem.SubSource)
+			dataCount, dataList, err := data.GetPageData(sourceEdbInfoItem.EdbInfoId, sourceEdbInfoItem.Source, sourceEdbInfoItem.SubSource, "", startSize, pageSize)
 			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, sourceEdbInfoItem.SubSource, pageSize, startSize)
-			if err != nil {
-				br.Msg = "获取指标信息失败"
-				br.ErrMsg = "获取指标数据失败,Err:" + err.Error()
-				return
-			}
 			edbInfoItem.DataList = dataList
 		}
 
@@ -385,37 +373,19 @@ func (this *PredictEdbInfoController) List() {
 	} else {
 		//获取指标数据(实际已生成)
 		{
-			var dataCondition string
-			var dataPars []interface{}
-
-			dataCondition += ` AND edb_info_id=? AND data_time <= ? `
-			dataPars = append(dataPars, edbInfoItem.EdbInfoId, edbInfoItem.LatestDate)
-
-			dataCount, err := data_manage.GetEdbDataCountByCondition(dataCondition, dataPars, edbInfoItem.Source, edbInfoItem.SubSource)
+			dataCount, dataList, err := data.GetPageData(edbInfoItem.EdbInfoId, edbInfoItem.Source, edbInfoItem.SubSource, edbInfoItem.LatestDate, startSize, pageSize)
 			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
 		}
 
 		// 第一页才需要 获取预测指标未来的数据
 		if currentIndex == 1 {
-			var dataCondition string
-			var dataPars []interface{}
-
-			dataCondition += ` AND edb_info_id=? AND data_time > ? `
-			dataPars = append(dataPars, edbInfoItem.EdbInfoId, edbInfoItem.LatestDate)
-
-			predictDataList, err = data_manage.GetAllEdbDataListByCondition(dataCondition, dataPars, edbInfoItem.Source, edbInfoItem.SubSource)
+			predictDataList, err = data_manage.GetAllEdbDataListData(edbInfoItem.EdbInfoId, edbInfoItem.Source, edbInfoItem.SubSource, edbInfoItem.LatestDate)
 			if err != nil {
 				br.Msg = "获取指标信息失败"
 				br.ErrMsg = "获取指标数据失败,Err:" + err.Error()

+ 18 - 2
controllers/data_manage/supply_analysis/variety_edb.go

@@ -95,8 +95,24 @@ func (this *VarietyController) EdbList() {
 		}
 
 		if tmpItem, ok := edbInfoAndClassifyMap[v.EdbInfoId]; ok {
-			v.ClassifyName = tmpItem.FirstClassifyName + "/" + tmpItem.SecondClassifyName
-			v.ClassifyId = tmpItem.SecondClassifyId
+			classifyNameList := make([]string, 0)
+
+			// 所属分类
+			{
+				classifyList, tmpErr, errMsg := data.GetFullClassifyByClassifyId(tmpItem.ClassifyId)
+				if tmpErr != nil {
+					br.Msg = errMsg
+					br.ErrMsg = "获取ETA指标的分类信息失败,Err:" + err.Error()
+					return
+				}
+				for _, tmpClassify := range classifyList {
+					classifyNameList = append(classifyNameList, tmpClassify.ClassifyName)
+				}
+			}
+
+			v.ClassifyName = strings.Join(classifyNameList, "/")
+
+			v.ClassifyId = tmpItem.ClassifyId
 			v.EdbCode = tmpItem.EdbCode
 			v.UniqueCode = tmpItem.UniqueCode
 		} else {

+ 13 - 0
go.mod

@@ -29,6 +29,7 @@ require (
 	github.com/mojocn/base64Captcha v1.3.6
 	github.com/nosixtools/solarlunar v0.0.0-20211112060703-1b6dea7b4a19
 	github.com/olivere/elastic/v7 v7.0.32
+	github.com/qiniu/qmgo v1.1.8
 	github.com/rdlucklib/rdluck_tools v1.0.3
 	github.com/shopspring/decimal v1.3.1
 	github.com/silenceper/wechat/v2 v2.1.6
@@ -38,6 +39,7 @@ require (
 	github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ses v1.0.880
 	github.com/xuri/excelize/v2 v2.8.1
 	github.com/yidane/formula v0.0.0-20220322063702-c9da84ba3476
+	go.mongodb.org/mongo-driver v1.15.0
 	gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
 )
 
@@ -58,8 +60,12 @@ require (
 	github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
 	github.com/dustin/go-humanize v1.0.1 // indirect
 	github.com/fatih/structs v1.1.0 // indirect
+	github.com/go-playground/locales v0.13.0 // indirect
+	github.com/go-playground/universal-translator v0.17.0 // indirect
+	github.com/go-playground/validator/v10 v10.4.1 // indirect
 	github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
 	github.com/golang/protobuf v1.5.3 // indirect
+	github.com/golang/snappy v0.0.1 // indirect
 	github.com/gonum/blas v0.0.0-20181208220705-f22b278b28ac // indirect
 	github.com/gonum/floats v0.0.0-20181209220543-c233463c7e82 // indirect
 	github.com/gonum/integrate v0.0.0-20181209220457-a422b5c0fdf2 // indirect
@@ -73,6 +79,7 @@ require (
 	github.com/json-iterator/go v1.1.12 // indirect
 	github.com/klauspost/compress v1.17.6 // indirect
 	github.com/klauspost/cpuid/v2 v2.2.6 // indirect
+	github.com/leodido/go-urn v1.2.0 // indirect
 	github.com/mailru/easyjson v0.7.7 // indirect
 	github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
 	github.com/minio/md5-simd v1.1.2 // indirect
@@ -81,6 +88,7 @@ require (
 	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
 	github.com/modern-go/reflect2 v1.0.2 // indirect
 	github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
+	github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe // indirect
 	github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b // indirect
 	github.com/pkg/errors v0.9.1 // indirect
 	github.com/prometheus/client_golang v1.16.0 // indirect
@@ -97,11 +105,16 @@ require (
 	github.com/tidwall/match v1.1.1 // indirect
 	github.com/tidwall/pretty v1.2.0 // indirect
 	github.com/tjfoc/gmsm v1.3.2 // indirect
+	github.com/xdg-go/pbkdf2 v1.0.0 // indirect
+	github.com/xdg-go/scram v1.1.2 // indirect
+	github.com/xdg-go/stringprep v1.0.4 // indirect
 	github.com/xuri/efp v0.0.0-20231025114914-d1ff6096ae53 // indirect
 	github.com/xuri/nfp v0.0.0-20230919160717-d98342af3f05 // indirect
+	github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect
 	golang.org/x/crypto v0.19.0 // indirect
 	golang.org/x/image v0.14.0 // indirect
 	golang.org/x/net v0.21.0 // indirect
+	golang.org/x/sync v0.2.0 // indirect
 	golang.org/x/sys v0.17.0 // indirect
 	golang.org/x/text v0.14.0 // indirect
 	golang.org/x/time v0.0.0-20181108054448-85acf8d2951c // indirect

+ 38 - 0
go.sum

@@ -138,6 +138,14 @@ github.com/go-ldap/ldap v3.0.3+incompatible h1:HTeSZO8hWMS1Rgb2Ziku6b8a7qRIZZMHj
 github.com/go-ldap/ldap v3.0.3+incompatible/go.mod h1:qfd9rJvER9Q0/D/Sqn1DfHRoBp40uXYvFoEVrNEPqRc=
 github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
 github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
+github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
+github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
+github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
+github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
+github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
+github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
+github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE=
+github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
 github.com/go-redis/redis v6.14.2+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
 github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
 github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
@@ -177,6 +185,8 @@ github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg
 github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
 github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
 github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
+github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
+github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
 github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
 github.com/gonum/blas v0.0.0-20181208220705-f22b278b28ac h1:Q0Jsdxl5jbxouNs1TQYt0gxesYMU4VXRbsTlgDloZ50=
 github.com/gonum/blas v0.0.0-20181208220705-f22b278b28ac/go.mod h1:P32wAyui1PQ58Oce/KYkOqQv8cVw1zAapXOl+dRFGbc=
@@ -197,6 +207,7 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a
 github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
 github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
 github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
@@ -245,6 +256,7 @@ github.com/jung-kurt/gofpdf v1.16.2/go.mod h1:1hl7y57EsiPAkLbOwzpzqgx1A30nQCk/Ym
 github.com/kgiannakakis/mp3duration v0.0.0-20191013070830-d834f8d5ed53 h1:+8X3HMX8A2QhvNg3dImiQTCiVUt6BQXz1mW+/DrWI+k=
 github.com/kgiannakakis/mp3duration v0.0.0-20191013070830-d834f8d5ed53/go.mod h1:E61jD6q4yJ6Cu9uDGRAfiENM1G5TVZhOog0Y3+GgTpQ=
 github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
+github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
 github.com/klauspost/compress v1.17.6 h1:60eq2E/jlfwQXtvZEeBUYADs+BwKBWURIY+Gj2eRGjI=
 github.com/klauspost/compress v1.17.6/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM=
 github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
@@ -260,6 +272,8 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
 github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
 github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
 github.com/ledisdb/ledisdb v0.0.0-20200510135210-d35789ec47e6/go.mod h1:n931TsDuKuq+uX4v1fulaMbA/7ZLLhjc85h7chZGBCQ=
+github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
+github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
 github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
 github.com/lib/pq v1.10.4/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
 github.com/lib/pq v1.10.5 h1:J+gdV2cUmX7ZqL2B0lFcW0m+egaHC2V3lpO8nWxyYiQ=
@@ -292,6 +306,8 @@ github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9
 github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
 github.com/mojocn/base64Captcha v1.3.6 h1:gZEKu1nsKpttuIAQgWHO+4Mhhls8cAKyiV2Ew03H+Tw=
 github.com/mojocn/base64Captcha v1.3.6/go.mod h1:i5CtHvm+oMbj1UzEPXaA8IH/xHFZ3DGY3Wh3dBpZ28E=
+github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe h1:iruDEfMl2E6fbMZ9s0scYfZQ84/6SPL6zC8ACM2oIL0=
+github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
 github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
 github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms=
 github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
@@ -353,6 +369,8 @@ github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsT
 github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
 github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg=
 github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM=
+github.com/qiniu/qmgo v1.1.8 h1:E64M+P59aqQpXKI24ClVtluYkLaJLkkeD2hTVhrdMks=
+github.com/qiniu/qmgo v1.1.8/go.mod h1:QvZkzWNEv0buWPx0kdZsSs6URhESVubacxFPlITmvB8=
 github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
 github.com/rdlucklib/rdluck_tools v1.0.3 h1:iOtK2QPlPQ6CL6c1htCk5VnFCHzyG6DCfJtunrMswK0=
 github.com/rdlucklib/rdluck_tools v1.0.3/go.mod h1:9Onw9o4w19C8KE5lxb8GyxgRBbZweRVkQSc79v38EaA=
@@ -391,11 +409,13 @@ github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU
 github.com/ssdb/gossdb v0.0.0-20180723034631-88f6b59b84ec/go.mod h1:QBvMkMya+gXctz3kmljlUCu/yB3GZ6oee+dUozsezQE=
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48=
 github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
 github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
 github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
 github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
 github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
+github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
@@ -415,6 +435,7 @@ github.com/tidwall/gjson v1.14.1 h1:iymTbGkQBhveq21bEvAQ81I0LEBork8BFe1CUZXdyuo=
 github.com/tidwall/gjson v1.14.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
 github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
 github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
+github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
 github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
 github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
 github.com/tjfoc/gmsm v1.3.2 h1:7JVkAn5bvUJ7HtU08iW6UiD+UTmJTIToHCfeFzkcCxM=
@@ -425,6 +446,14 @@ github.com/uber/jaeger-lib v2.4.1+incompatible h1:td4jdvLcExb4cBISKIpHuGoVXh+dVK
 github.com/uber/jaeger-lib v2.4.1+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U=
 github.com/ugorji/go v0.0.0-20171122102828-84cb69a8af83/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ=
 github.com/wendal/errors v0.0.0-20130201093226-f66c77a7882b/go.mod h1:Q12BUT7DqIlHRmgv3RskH+UCM/4eqVMgI0EMmlSpAXc=
+github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
+github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
+github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g=
+github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY=
+github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4=
+github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8=
+github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8=
+github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM=
 github.com/xuri/efp v0.0.0-20231025114914-d1ff6096ae53 h1:Chd9DkqERQQuHpXjR/HSV1jLZA6uaoiwwH3vSuF3IW0=
 github.com/xuri/efp v0.0.0-20231025114914-d1ff6096ae53/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI=
 github.com/xuri/excelize/v2 v2.8.1 h1:pZLMEwK8ep+CLIUWpWmvW8IWE/yxqG0I1xcN6cVMGuQ=
@@ -434,6 +463,8 @@ github.com/xuri/nfp v0.0.0-20230919160717-d98342af3f05/go.mod h1:WwHg+CVyzlv/TX9
 github.com/yidane/formula v0.0.0-20220322063702-c9da84ba3476 h1:66fLxv8xlhSr42ZhVAYjUY/sEF0olUUAESVlsxVduuw=
 github.com/yidane/formula v0.0.0-20220322063702-c9da84ba3476/go.mod h1:9/dQiKiN04yPMdgsuFmKGuI2Hdp6OmFV9gSWS1col6g=
 github.com/ylywyn/jpush-api-go-client v0.0.0-20190906031852-8c4466c6e369/go.mod h1:Nv7wKD2/bCdKUFNKcJRa99a+1+aSLlCRJFriFYdjz/I=
+github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d h1:splanxYIlg+5LfHAM6xpdFEAYOk8iySO56hMFq6uLyA=
+github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
 github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.1.30/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
@@ -443,6 +474,9 @@ github.com/yuin/gopher-lua v0.0.0-20220504180219-658193537a64 h1:5mLPGnFdSsevFRF
 github.com/yuin/gopher-lua v0.0.0-20220504180219-658193537a64/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw=
 github.com/ziutek/mymysql v1.5.4 h1:GB0qdRGsTwQSBVYuVShFBKaXSnSnYYC2d9knnE1LHFs=
 github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0=
+go.mongodb.org/mongo-driver v1.11.6/go.mod h1:G9TgswdsWjX4tmDA5zfs2+6AEPpYJwqblyjsfuh8oXY=
+go.mongodb.org/mongo-driver v1.15.0 h1:rJCKC8eEliewXjZGf0ddURtl7tTVy1TK3bfl0gkUSLc=
+go.mongodb.org/mongo-driver v1.15.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c=
 go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
 go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
 go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
@@ -521,8 +555,11 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
 golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI=
+golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -572,6 +609,7 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
+golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
 golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
 golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
 golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=

+ 16 - 0
models/business_conf.go

@@ -1,6 +1,7 @@
 package models
 
 import (
+	"eta/eta_mobile/utils"
 	"fmt"
 	"github.com/beego/beego/v2/client/orm"
 	"html"
@@ -220,3 +221,18 @@ func GetBusinessConfByKey(key string) (item *BusinessConf, err error) {
 	err = o.Raw(sql, key).QueryRow(&item)
 	return
 }
+
+// InitUseMongoConf
+// @Description:
+// @author: Roc
+// @datetime 2024-07-01 13:49:09
+func InitUseMongoConf() {
+	useMongo, e := GetBusinessConfByKey("UseMongo")
+	if e != nil {
+		return
+	}
+
+	if useMongo.ConfVal == `true` {
+		utils.UseMongo = true
+	}
+}

+ 231 - 0
models/data_manage/base_from_business_data.go

@@ -0,0 +1,231 @@
+package data_manage
+
+import (
+	"eta/eta_mobile/utils"
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
+	"strings"
+	"time"
+)
+
+// BaseFromBusinessData
+// @Description: 外部指标(商家系统)原始数据表
+type BaseFromBusinessData struct {
+	BusinessDataId          int       `orm:"column(business_data_id);pk" json:"business_data_id"`
+	BaseFromBusinessIndexId int       `json:"base_from_business_index_id"` // 指标id
+	IndexCode               string    `json:"index_code"`                  // 指标编码
+	DataTime                time.Time `json:"data_time"`                   // 数据日期
+	Value                   float64   `json:"value"`                       // 数据值
+	CreateTime              time.Time `json:"create_time"`                 // 创建时间
+	ModifyTime              time.Time `json:"modify_time"`                 // 修改时间
+}
+
+// TableName
+// @Description:  获取表名
+// @author: Roc
+// @receiver m
+// @datetime 2024-04-26 13:41:36
+// @return string
+func (m *BaseFromBusinessData) TableName() string {
+	return "base_from_business_data"
+}
+
+// CollectionName
+// @Description:  获取集合名称
+// @author: Roc
+// @receiver m
+// @datetime 2024-04-26 13:41:36
+// @return string
+func (m *BaseFromBusinessData) CollectionName() string {
+	return "base_from_business_data"
+}
+
+// DataBaseName
+// @Description: 获取数据库名称
+// @author: Roc
+// @receiver m
+// @datetime 2024-04-26 13:41:33
+// @return string
+func (m *BaseFromBusinessData) DataBaseName() string {
+	return utils.MgoDataDbName
+}
+
+type WhereParams struct {
+	Condition string
+	Pars      []interface{}
+	Order     string `description:"排序字段"`
+}
+
+// GetAllDataList
+// @Description: 根据条件获取所有数据
+// @author: Roc
+// @receiver m
+// @datetime 2024-04-26 13:42:19
+// @param sort []string
+// @param whereParams interface{}
+// @return result []BaseFromBusinessData
+// @return err error
+func (m *BaseFromBusinessData) GetAllDataList(condition string, pars []interface{}, order string) (result []*BaseFromBusinessData, err error) {
+	o := orm.NewOrmUsingDB("data")
+
+	sql := `SELECT * FROM base_from_business_data WHERE 1=1 `
+	if condition != `` {
+		sql += ` ` + condition
+	}
+
+	if order != `` {
+		sql += ` ORDER BY ` + order
+	}
+
+	_, err = o.Raw(sql, pars).QueryRows(&result)
+
+	return
+}
+
+// GetLimitDataList
+// @Description: 根据条件获取指定数量数据列表
+// @author: Roc
+// @receiver m
+// @datetime 2024-05-06 17:08:32
+// @param whereParams interface{}
+// @param size int64
+// @return result []*BaseFromBusinessData
+// @return err error
+func (m *BaseFromBusinessData) GetLimitDataList(condition string, pars []interface{}, order string, size int64) (result []*BaseFromBusinessData, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT * FROM base_from_business_data WHERE 1=1 `
+	if condition != `` {
+		sql += ` ` + condition
+	}
+
+	if order != `` {
+		sql += ` ORDER BY ` + order
+	}
+
+	sql += fmt.Sprintf(` LIMIT %d`, size)
+
+	_, err = o.Raw(sql, pars).QueryRows(&result)
+
+	return
+}
+
+// GetPageDataList
+// @Description: 根据条件获取分页数据列表
+// @author: Roc
+// @receiver m
+// @datetime 2024-05-07 10:21:07
+// @param whereParams interface{}
+// @param startSize int64
+// @param size int64
+// @param sort []string
+// @return result []*BaseFromBusinessData
+// @return err error
+func (m *BaseFromBusinessData) GetPageDataList(condition []string, pars []interface{}, order string, startSize, size int64) (result []*BaseFromBusinessData, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT * FROM base_from_business_data `
+	if len(condition) > 0 {
+		sql += ` WHERE ` + strings.Join(condition, " AND ")
+	}
+
+	if order != `` {
+		sql += ` ORDER BY ` + order
+	}
+
+	sql += fmt.Sprintf(` LIMIT %d,%d`, startSize, size)
+
+	_, err = o.Raw(sql, pars).QueryRows(&result)
+
+	return
+}
+
+// GetCountDataList
+// @Description:  根据条件获取数据列表总数
+// @author: Roc
+// @receiver m
+// @datetime 2024-05-07 10:29:00
+// @param whereParams interface{}
+// @return count int64
+// @return err error
+func (m *BaseFromBusinessData) GetCountDataList(condition []string, pars []interface{}) (count int64, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT COUNT(1) FROM base_from_business_data `
+	if len(condition) > 0 {
+		sql += ` WHERE ` + strings.Join(condition, " AND ")
+	}
+	err = o.Raw(sql, pars).QueryRow(&count)
+
+	return
+}
+
+// InsertDataByColl
+// @Description: 写入单条数据(外部传入集合)
+// @author: Roc
+// @receiver m
+// @datetime 2024-04-26 14:22:18
+// @param addData interface{}
+// @return err error
+func (m *BaseFromBusinessData) InsertDataByColl(addData interface{}) (err error) {
+	o := orm.NewOrmUsingDB("data")
+	_, err = o.Insert(addData)
+
+	return
+}
+
+// BatchInsertData
+// @Description: 批量写入数据
+// @author: Roc
+// @receiver m
+// @datetime 2024-04-26 14:22:18
+// @param bulk int 每次请求保存的数据量
+// @param dataList []interface{}
+// @return err error
+func (m *BaseFromBusinessData) BatchInsertData(bulk int, dataList []interface{}) (err error) {
+	o := orm.NewOrmUsingDB("data")
+	_, err = o.InsertMulti(bulk, dataList)
+
+	return
+}
+
+// UpdateData
+// @Description: 单条数据修改
+// @author: Roc
+// @receiver m
+// @datetime 2024-04-26 15:01:51
+// @param whereParams interface{}
+// @param updateParams interface{}
+// @return err error
+func (m *BaseFromBusinessData) UpdateData(updateCols []string) (err error) {
+	o := orm.NewOrmUsingDB("data")
+	_, err = o.Update(m, updateCols...)
+	if err != nil {
+		fmt.Println("UpdateDataByColl:Err:" + err.Error())
+		return
+	}
+
+	return
+}
+
+// GetEdbInfoMaxAndMinInfo
+// @Description: 获取当前指标的最大最小值
+// @author: Roc
+// @receiver m
+// @datetime 2024-04-30 17:15:39
+// @param whereParams interface{}
+// @return result EdbInfoMaxAndMinInfo
+// @return err error
+func (m *BaseFromBusinessData) GetEdbInfoMaxAndMinInfo(indexCode string) (result EdbInfoMaxAndMinInfo, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ``
+	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 base_from_business_data WHERE index_code = ? `
+	err = o.Raw(sql, indexCode).QueryRow(&result)
+	if err != nil {
+		return
+	}
+
+	var latestValue float64
+	sql = ` SELECT value AS latest_value FROM base_from_business_data WHERE index_code = ? ORDER BY data_time DESC LIMIT 1 `
+	err = o.Raw(sql, indexCode).QueryRow(&latestValue)
+	result.LatestValue = latestValue
+
+	return
+}

+ 252 - 0
models/data_manage/base_from_business_index.go

@@ -0,0 +1,252 @@
+package data_manage
+
+import (
+	"eta/eta_mobile/utils"
+	"github.com/beego/beego/v2/client/orm"
+	"github.com/rdlucklib/rdluck_tools/paging"
+	"time"
+)
+
+// BaseFromBusinessIndex
+// @Description: 外部指标(商家系统)表
+type BaseFromBusinessIndex struct {
+	BaseFromBusinessIndexId int64     `orm:"column(base_from_business_index_id);pk"`
+	IndexCode               string    `description:"指标编码"`
+	IndexName               string    `description:"指标名称"`
+	Unit                    string    `description:"单位"`
+	Frequency               string    `description:"频度"`
+	Source                  int       `description:"数据来源"`
+	SourceName              string    `description:"数据来源名称"`
+	StartDate               time.Time `description:"开始日期"`
+	EndDate                 time.Time `description:"结束日期"`
+	Remark                  string    `description:"备注字段"`
+	BaseModifyTime          time.Time `description:"基础信息(名称,单位,频度)变更时间"`
+	DataUpdateTime          time.Time `description:"最近一次数据发生变化的时间"`
+	CreateTime              time.Time `description:"创建时间"`
+	ModifyTime              time.Time `description:"修改时间"`
+}
+
+var BaseFromBusinessIndexCols = struct {
+	BaseFromBusinessIndexId string
+	IndexCode               string
+	IndexName               string
+	Unit                    string
+	Frequency               string
+	Source                  string
+	SourceName              string
+	StartDate               string
+	EndDate                 string
+	Remark                  string
+	BaseModifyTime          string
+	DataUpdateTime          string
+	CreateTime              string
+	ModifyTime              string
+}{
+	BaseFromBusinessIndexId: "base_from_business_index_id",
+	IndexCode:               "index_code",
+	IndexName:               "index_name",
+	Unit:                    "unit",
+	Frequency:               "frequency",
+	Source:                  "source",
+	SourceName:              "source_name",
+	StartDate:               "start_date",
+	EndDate:                 "end_date",
+	Remark:                  "remark",
+	BaseModifyTime:          "base_modify_time",
+	DataUpdateTime:          "data_update_time",
+	CreateTime:              "create_time",
+	ModifyTime:              "modify_time",
+}
+
+// EdbBusinessSource
+// @Description: 自有数据(商家)指标来源
+type EdbBusinessSource struct {
+	EdbBusinessSourceId int64     `orm:"column(edb_business_source_id);pk"`
+	SourceName          string    `description:"来源名称"` // 来源名称
+	CreateTime          time.Time `description:"创建时间"` // 创建时间
+}
+
+// GetEdbBusinessSourceItem
+// @Description: 根据来源名称获取来源信息
+// @author: Roc
+// @receiver m
+// @datetime 2024-04-25 18:09:03
+// @param sourceName string
+// @return item *EdbBusinessSource
+// @return err error
+func (m *EdbBusinessSource) GetEdbBusinessSourceItem(sourceName string) (item *EdbBusinessSource, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT * FROM edb_business_source WHERE source_name = ? `
+	err = o.Raw(sql, sourceName).QueryRow(&item)
+	return
+}
+
+// GetAllList
+// @Description: 获取所有来源列表
+// @author: Roc
+// @receiver m
+// @datetime 2024-05-06 09:21:42
+// @return items []*EdbBusinessSource
+// @return err error
+func (m *EdbBusinessSource) GetAllList() (items []*EdbBusinessSource, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT * FROM edb_business_source order by  edb_business_source_id desc `
+	_, err = o.Raw(sql).QueryRows(&items)
+
+	return
+}
+
+// GetListCount
+// @Description: 根据条件获取列表页的总数量
+// @author: Roc
+// @receiver m
+// @datetime 2024-05-06 17:15:28
+// @param condition string
+// @param pars []interface{}
+// @return count int
+// @return err error
+func (m *BaseFromBusinessIndex) GetListCount(condition string, pars []interface{}) (count int, err error) {
+	sql := ` select count(1) as count FROM base_from_business_index as a WHERE 1=1 `
+	if condition != "" {
+		sql += condition
+	}
+	o := orm.NewOrmUsingDB("data")
+	err = o.Raw(sql, pars).QueryRow(&count)
+
+	return
+}
+
+// GetList
+// @Description: 根据条件获取列表页的数据
+// @author: Roc
+// @receiver m
+// @datetime 2024-05-06 17:15:42
+// @param condition string
+// @param pars []interface{}
+// @param startSize int
+// @param pageSize int
+// @return items []*BaseFromBusinessIndex
+// @return err error
+func (m *BaseFromBusinessIndex) GetList(condition string, pars []interface{}, startSize, pageSize int) (items []*BaseFromBusinessIndex, err error) {
+	sql := `select * FROM base_from_business_index AS a  WHERE 1=1 `
+	if condition != "" {
+		sql += condition
+	}
+	sql += ` order by a.base_from_business_index_id desc limit ?,? `
+	o := orm.NewOrmUsingDB("data")
+	_, err = o.Raw(sql, pars, startSize, pageSize).QueryRows(&items)
+
+	return
+}
+
+// BusinessIndexListResp
+// @Description: 外部(商家)指标列表返回
+type BusinessIndexListResp struct {
+	List   []*BaseFromBusinessIndexItem
+	Paging *paging.PagingItem `description:"分页数据"`
+}
+
+// BaseFromBusinessIndexItem
+// @Description: 外部指标(商家系统)结构
+type BaseFromBusinessIndexItem struct {
+	BaseFromBusinessIndexId int64  `orm:"column(base_from_business_index_id);pk"`
+	IndexCode               string `description:"指标编码"`
+	IndexName               string `description:"指标名称"`
+	Unit                    string `description:"单位"`
+	Frequency               string `description:"频度"`
+	Source                  int    `description:"数据来源"`
+	SourceName              string `description:"数据来源名称"`
+	StartDate               string `description:"开始日期"`
+	EndDate                 string `description:"结束日期"`
+	Remark                  string `description:"备注字段"`
+	BaseModifyTime          string `description:"基础信息(名称,单位,频度)变更时间"`
+	DataUpdateTime          string `description:"最近一次数据发生变化的时间"`
+	CreateTime              string `description:"创建时间"`
+	ModifyTime              string `description:"修改时间"`
+	EdbInfoId               int    `description:"eta指标库的id"`
+	EdbUniqueCode           string `description:"指标库唯一编码"`
+	EdbClassifyId           int    `description:"指标库分类ID"`
+	EdbExist                int    `description:"指标库是否已添加:0-否;1-是"`
+}
+
+func (m *BaseFromBusinessIndex) GetPageItemsByCondition(condition string, pars []interface{}, orderRule string, startSize, pageSize int) (items []*BaseFromBusinessIndexItem, err error) {
+	sql := `select a.*,b.edb_info_id,b.unique_code as edb_unique_code,b.classify_id as edb_classify_id FROM base_from_business_index AS a LEFT JOIN edb_info b on a.index_code=b.edb_code AND b.source=? WHERE 1=1 `
+	if condition != "" {
+		sql += condition
+	}
+	if orderRule == `` {
+		sql += ` order by a.base_from_business_index_id desc`
+	} else {
+		sql += ` order by ` + orderRule
+	}
+	sql += ` limit ?,? `
+	o := orm.NewOrmUsingDB("data")
+	_, err = o.Raw(sql, utils.DATA_SOURCE_BUSINESS, pars, startSize, pageSize).QueryRows(&items)
+
+	return
+}
+
+// GeItemsByCondition
+// @Description: 根据条件获取指定数量的指标
+// @author: Roc
+// @receiver m
+// @datetime 2024-05-06 17:16:02
+// @param condition string
+// @param pars []interface{}
+// @param limitSize int
+// @return items []*BaseFromBusinessIndexItem
+// @return err error
+func (m *BaseFromBusinessIndex) GeItemsByCondition(condition string, pars []interface{}, limitSize int) (items []*BaseFromBusinessIndexItem, err error) {
+	if pars == nil {
+		pars = make([]interface{}, 0)
+	}
+
+	sql := `select a.*,b.edb_info_id,b.unique_code as edb_unique_code,b.classify_id as edb_classify_id FROM base_from_business_index AS a LEFT JOIN edb_info b on a.index_code=b.edb_code AND b.source=? WHERE 1=1 `
+	if condition != "" {
+		sql += condition
+	}
+	sql += ` order by a.base_from_business_index_id desc `
+
+	if limitSize > 0 {
+		sql += " limit ? "
+		pars = append(pars, limitSize)
+	}
+
+	o := orm.NewOrmUsingDB("data")
+	_, err = o.Raw(sql, utils.DATA_SOURCE_BUSINESS, pars).QueryRows(&items)
+
+	return
+}
+
+// GetDetailByEdbCode
+// @Description: 根据edbCode获取指标详情
+// @author: Roc
+// @receiver m
+// @datetime 2024-05-07 11:00:07
+// @param edbCode string
+// @return item *BaseFromBusinessIndex
+// @return err error
+func (m *BaseFromBusinessIndex) GetDetailByEdbCode(edbCode string) (item *BaseFromBusinessIndex, err error) {
+	sql := `select *  FROM base_from_business_index  WHERE index_code = ? `
+	o := orm.NewOrmUsingDB("data")
+	err = o.Raw(sql, edbCode).QueryRow(&item)
+
+	return
+}
+
+// BusinessIndexDataListResp
+// @Description: 外部(商家)指标数据列表返回
+type BusinessIndexDataListResp struct {
+	List   []*BaseFromBusinessIndexDataItem
+	Paging *paging.PagingItem `description:"分页数据"`
+}
+
+// BaseFromBusinessIndexDataItem
+// @Description: 外部指标(商家系统)数据结构
+type BaseFromBusinessIndexDataItem struct {
+	ID        string
+	EdbDataId int `orm:"column(edb_data_id);pk"`
+	IndexCode string
+	DataTime  string
+	Value     float64
+}

+ 10 - 0
models/data_manage/chart_edb_mapping.go

@@ -307,3 +307,13 @@ func ModifyChartEdbMapping(chartInfoId int, edbInfoList []*EdbInfo) (err error)
 
 	return
 }
+
+func GetChartMappingList(chartInfoId int) (list []*ChartEdbMapping, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT a.*
+             FROM chart_edb_mapping AS a
+			 WHERE chart_info_id=? 
+             ORDER BY chart_edb_mapping_id ASC `
+	_, err = o.Raw(sql, chartInfoId).QueryRows(&list)
+	return
+}

+ 331 - 44
models/data_manage/chart_info.go

@@ -2,10 +2,12 @@ package data_manage
 
 import (
 	"errors"
+	"eta/eta_mobile/models/mgo"
 	"eta/eta_mobile/utils"
 	"fmt"
 	"github.com/beego/beego/v2/client/orm"
 	"github.com/rdlucklib/rdluck_tools/paging"
+	"go.mongodb.org/mongo-driver/bson"
 	"strconv"
 	"strings"
 	"time"
@@ -369,8 +371,39 @@ type EdbDataList struct {
 	Value         float64 `description:"数据值"`
 }
 
-// GetEdbDataList 获取指标的数据(日期正序返回)
-func GetEdbDataList(source, subSource, endInfoId int, startDate, endDate string) (list []*EdbDataList, err error) {
+// GetEdbDataList
+// @Description: 获取指标的数据(日期正序返回)
+// @author: Roc
+// @datetime 2024-05-07 10:48:43
+// @param source int
+// @param subSource int
+// @param edbInfoId int
+// @param startDate string
+// @param endDate string
+// @return list []*EdbDataList
+// @return err error
+func GetEdbDataList(source, subSource, edbInfoId int, startDate, endDate string) (list []*EdbDataList, err error) {
+	// 自有数据需要额外处理(从mongo获取)
+	if source == utils.DATA_SOURCE_BUSINESS && utils.UseMongo {
+		return getEdbDataListByMongo(source, subSource, edbInfoId, startDate, endDate)
+	}
+
+	return getEdbDataListByMysql(source, subSource, edbInfoId, startDate, endDate)
+
+}
+
+// getEdbDataListByMysql
+// @Description: 通过mysql查询指标数据
+// @author: Roc
+// @datetime 2024-05-07 10:40:43
+// @param source int
+// @param subSource int
+// @param edbInfoId int
+// @param startDate string
+// @param endDate string
+// @return list []*EdbDataList
+// @return err error
+func getEdbDataListByMysql(source, subSource, edbInfoId int, startDate, endDate string) (list []*EdbDataList, err error) {
 	tableName := GetEdbDataTableName(source, subSource)
 	if tableName == "" {
 		err = errors.New("无效的渠道:" + strconv.Itoa(source))
@@ -391,43 +424,65 @@ func GetEdbDataList(source, subSource, endInfoId int, startDate, endDate string)
 	sql += ` ORDER BY data_time ASC `
 	sql = fmt.Sprintf(sql, tableName)
 	o := orm.NewOrmUsingDB("data")
-	_, err = o.Raw(sql, endInfoId, pars).QueryRows(&list)
+	_, err = o.Raw(sql, edbInfoId, pars).QueryRows(&list)
 	return
 }
 
-type EdbDataListByUniqueCode struct {
-	EdbDataId     int     `description:" 指标数据ID" json:"-"`
-	EdbInfoId     int     `description:"指标ID" json:"-"`
-	DataTime      string  //`json:"-" description:"数据日期"`
-	DataTimestamp int64   `description:"数据日期"`
-	Value         float64 `description:"数据值"`
-}
+// getEdbDataListByMongo
+// @Description: 通过mongo查询指标数据
+// @author: Roc
+// @datetime 2024-05-07 10:40:43
+// @param source int
+// @param subSource int
+// @param endInfoId int
+// @param startDate string
+// @param endDate string
+// @return list []*EdbDataList
+// @return err error
+func getEdbDataListByMongo(source, subSource, edbInfoId int, startDate, endDate string) (list []*EdbDataList, err error) {
+	list = make([]*EdbDataList, 0)
 
-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)
-		return list, err
+	mogDataObj := mgo.EdbDataBusiness{}
+	// 构建查询条件
+	queryConditions := bson.M{
+		"edb_info_id": edbInfoId,
 	}
-	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)
+	// 数据日期
+	dateCondition, err := mgo.BuildDateCondition(startDate, endDate)
+	if err != nil {
+		return
 	}
-	if endDate != "" {
-		sql += ` AND data_time<=? `
-		pars = append(pars, endDate)
+	if len(dateCondition) > 0 {
+		queryConditions["data_time"] = dateCondition
+	}
+
+	// 获取列表数据
+	tmpDataList, tmpErr := mogDataObj.GetAllDataList(queryConditions, []string{"data_time"})
+	if tmpErr != nil {
+		err = tmpErr
+		return
+	}
+	for k, v := range tmpDataList {
+		list = append(list, &EdbDataList{
+			EdbDataId:     k + 1,
+			EdbInfoId:     v.EdbInfoId,
+			DataTime:      v.DataTime.Format(utils.FormatDate),
+			DataTimestamp: v.DataTimestamp,
+			Value:         v.Value,
+		})
 	}
 
-	sql += ` ORDER BY data_time ASC `
-	sql = fmt.Sprintf(sql, tableName)
-	o := orm.NewOrmUsingDB("data")
-	_, err = o.Raw(sql, endInfoId, pars).QueryRows(&list)
 	return
 }
 
+type EdbDataListByUniqueCode struct {
+	EdbDataId     int     `description:" 指标数据ID" json:"-"`
+	EdbInfoId     int     `description:"指标ID" json:"-"`
+	DataTime      string  //`json:"-" description:"数据日期"`
+	DataTimestamp int64   `description:"数据日期"`
+	Value         float64 `description:"数据值"`
+}
+
 func GetEdbDataLunarList(endInfoId int, startDate, endDate string) (list []*EdbDataList, err error) {
 	tableName := "edb_data_quarter"
 	sql := `SELECT edb_data_id,edb_info_id,data_time,TRUNCATE(value,2) AS value,data_timestamp FROM %s WHERE edb_info_id=? AND data_time>=? AND data_time<=? ORDER BY data_time ASC `
@@ -437,7 +492,40 @@ func GetEdbDataLunarList(endInfoId int, startDate, endDate string) (list []*EdbD
 	return
 }
 
-func GetEdbDataListMinAndMax(source, subSource, endInfoId int, startDate, endDate string) (min_data, max_data float64, err error) {
+// GetEdbDataListMinAndMax
+// @Description: 根据条件数据库中获取指标数据最小值和最大值
+// @author: Roc
+// @datetime 2024-05-07 13:11:32
+// @param source int
+// @param subSource int
+// @param edbInfoId int
+// @param startDate string
+// @param endDate string
+// @return min_data float64
+// @return max_data float64
+// @return err error
+func GetEdbDataListMinAndMax(source, subSource, edbInfoId int, startDate, endDate string) (min_data, max_data float64, err error) {
+	// 自有数据需要额外处理(从mongo获取)
+	if source == utils.DATA_SOURCE_BUSINESS && utils.UseMongo {
+		return getEdbDataListMinAndMaxByMongo(source, subSource, edbInfoId, startDate, endDate)
+	}
+
+	return getEdbDataListMinAndMaxByMysql(source, subSource, edbInfoId, startDate, endDate)
+}
+
+// getEdbDataListMinAndMaxByMysql
+// @Description: 根据条件从mysql数据库中获取指标数据最小值和最大值
+// @author: Roc
+// @datetime 2024-05-07 13:11:22
+// @param source int
+// @param subSource int
+// @param edbInfoId int
+// @param startDate string
+// @param endDate string
+// @return minData float64
+// @return maxData float64
+// @return err error
+func getEdbDataListMinAndMaxByMysql(source, subSource, edbInfoId int, startDate, endDate string) (minData, maxData 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{}
@@ -460,7 +548,54 @@ func GetEdbDataListMinAndMax(source, subSource, endInfoId int, startDate, endDat
 		sql += condition
 	}
 
-	err = o.Raw(sql, endInfoId, pars).QueryRow(&min_data, &max_data)
+	err = o.Raw(sql, edbInfoId, pars).QueryRow(&minData, &maxData)
+	return
+}
+
+// getEdbDataListMinAndMaxByMongo
+// @Description: 根据条件从mongo数据库中获取指标数据最小值和最大值
+// @author: Roc
+// @datetime 2024-05-07 13:10:26
+// @param source int
+// @param subSource int
+// @param edbInfoId int
+// @param startDate string
+// @param endDate string
+// @return minData float64
+// @return maxData float64
+// @return err error
+func getEdbDataListMinAndMaxByMongo(source, subSource, edbInfoId int, startDate, endDate string) (minData, maxData float64, err error) {
+	mogDataObj := mgo.EdbDataBusiness{}
+	// 构建查询条件
+	queryConditions := bson.M{
+		"edb_info_id": edbInfoId,
+	}
+
+	// 数据日期
+	dateCondition, err := mgo.BuildDateCondition(startDate, endDate)
+	if err != nil {
+		return
+	}
+	if len(dateCondition) > 0 {
+		queryConditions["data_time"] = dateCondition
+	}
+
+	pipeline := []bson.M{
+		{"$match": queryConditions},
+		{"$group": bson.M{
+			"_id":       nil,
+			"min_value": bson.M{"$min": "$value"},
+			"max_value": bson.M{"$max": "$value"},
+		}},
+		{"$project": bson.M{"_id": 0}}, // 可选,如果不需要_id字段
+	}
+	result, err := mogDataObj.GetEdbInfoMaxAndMinInfo(pipeline)
+	if err != nil {
+		return
+	}
+	minData = result.MinValue
+	maxData = result.MaxValue
+
 	return
 }
 
@@ -468,6 +603,7 @@ type ChartEdbInfoMapping struct {
 	EdbInfoId           int     `description:"指标id"`
 	SourceName          string  `description:"来源名称"`
 	Source              int     `description:"来源id"`
+	SubSource           int     `description:"来源id"`
 	EdbCode             string  `description:"指标编码"`
 	EdbName             string  `description:"指标名称"`
 	EdbAliasName        string  `description:"指标名称(别名)"`
@@ -508,7 +644,6 @@ 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:"证券代码"`
@@ -579,6 +714,10 @@ type YData struct {
 	M              []int           `description:"对应开始日期的间隔值" json:"-"`
 	Unit           string          `description:"中文单位名称"`
 	UnitEn         string          `description:"英文单位名称"`
+	SeriesEdb      struct {
+		SeriesId  int `description:"因子指标系列ID"`
+		EdbInfoId int `description:"指标ID"`
+	} `description:"对应的系列指标"`
 }
 
 func ModifyChartInfoAndMapping(edbInfoIdStr string, req *SaveChartInfoReq, chartType int) (err error) {
@@ -1216,15 +1355,6 @@ func EditChartBaseInfoAndEdbEnInfo(req *EditChartInfoBaseReq, chartItem *ChartIn
 	return
 }
 
-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")
-	_, err = o.Raw(sql, dataTimestamp, edbDataId).Exec()
-	return
-}
-
 type AddChartInfoReq struct {
 	ChartEdbInfoList     []*ChartSaveItem        `description:"指标及配置信息"`
 	ChartClassifyId      int                     `description:"分类id"`
@@ -1268,10 +1398,14 @@ type PreviewChartInfoReq struct {
 }
 
 type SeasonExtraItem struct {
-	ChartLegend []SeasonChartLegend `description:"自定义的图例名称"`
-	XStartDate  string              `description:"横坐标显示的起始日"`
-	XEndDate    string              `description:"横坐标显示的截止日"`
-	JumpYear    int                 `description:"横坐标日期是否跨年,1跨年,0不跨年"`
+	ChartLegend                 []SeasonChartLegend         `description:"自定义的图例名称"`
+	XStartDate                  string                      `description:"横坐标显示的起始日"`
+	XEndDate                    string                      `description:"横坐标显示的截止日"`
+	JumpYear                    int                         `description:"横坐标日期是否跨年,1跨年,0不跨年"`
+	RightAxis                   SeasonRightAxis             `description:"自定义右轴指标"`
+	MaxMinLimits                MaxMinLimits                `description:"自定义同期上下限"`
+	SamePeriodAverage           SamePeriodAverage           `description:"自定义同期均线"`
+	SamePeriodStandardDeviation SamePeriodStandardDeviation `description:"自定义同期标准差"`
 }
 
 type SeasonChartLegend struct {
@@ -2213,3 +2347,156 @@ type RadarYData struct {
 	Name  string    `description:"别名"`
 	Value []float64 `description:"每个指标的值"`
 }
+
+type MarkersLine struct {
+	Axis             int             `json:"axis" description:"1左轴 2右轴 3横轴"`
+	AxisName         string          `json:"axisName" description:"轴的名称,例如'左轴'"`
+	MarkerType       string          `json:"markerType" description:"标识线或标识区"`
+	MarkLineType     int             `json:"markLineType" description:"1:固定 2:指标计算"`
+	Value            string          `json:"value" description:"连线指向的数值,例如'4000'"`
+	FromValue        string          `json:"fromValue" description:"连线的起始点,可以为空"`
+	ToValue          string          `json:"toValue" description:"连线的结束点,可以为空"`
+	LineWidth        float64         `json:"lineWidth" description:"连线的宽度"`
+	DashStyle        string          `json:"dashStyle" description:"连线的虚线样式,例如'ShortDashDot'"`
+	Color            string          `json:"color" description:"连线的颜色"`
+	Text             string          `json:"text" description:"连线旁边显示的文本"`
+	TextPosition     string          `json:"textPosition" description:"文本的显示位置,例如'bottom'"`
+	TextColor        string          `json:"textColor" description:"文本颜色"`
+	TextFontSize     int             `json:"textFontSize" description:"文本的字号大小"`
+	IsShow           bool            `json:"isShow" description:"是否显示连线及文本"`
+	EdbType          int             `json:"edbType" description:"指标类型 0图中第一个指标 1其他指标 前端回显用"`
+	EdbInfoId        int             `json:"edbInfoId" description:"指标id"`
+	Calculation      int             `json:"calculation" description:"计算方式 1区间均值 2区间均值加N倍标准差 3区间个数分位 4区间数值分位"`
+	CalculationValue float64         `json:"calculationValue" description:"计算方式对应的值 2就是几倍标准差 3就是分位值 4就是数值值·"`
+	TimeIntervalType int             `json:"timeInterval" description:"时间区间 0跟随图表 1自定义"`
+	StartDate        MarkersLineTime `json:"startTime" description:"开始时间"`
+	EndDate          MarkersLineTime `json:"endTime" description:"结束时间"`
+}
+
+type MarkersLineTime struct {
+	TimeType int               `json:"timeType" description:"时间类型 1固定 2动态 3至今(仅结束时间)"`
+	Date     string            `json:"date" description:"日期"`
+	Conf     EdbDateChangeConf `json:"conf" description:"动态时间配置"`
+}
+
+// EdbDateExtraConf
+// @Description: 导入指标日期前移和日期变换
+type EdbDateChangeConf struct {
+	MoveForward int `description:"前移的期数"`
+	BaseDate    int `description:"基准日期 0系统日期 1指标最新日期"`
+	DateChange  []*EdbDateConfDateChange
+}
+
+type EdbDateConfDateChange struct {
+	Year         int
+	Month        int
+	Day          int
+	Frequency    string `description:"频度变换"`
+	FrequencyDay string `description:"频度的固定日期"`
+	ChangeType   int    `description:"日期变换类型1日期位移,2指定频率"`
+}
+
+
+// 自定义右轴指标
+type SeasonRightAxis struct {
+	IndicatorType int     `description:"右轴指标类型 1:左轴指标同比,2:指标库,3:预测指标 "`
+	Style         string  `description:"生成样式"`
+	Shape         string  `description:"形状"`
+	ChartColor    string  `description:"图表颜色"`
+	Size          float64 `description:"大小"`
+	Legend        string  `description:"图例名称"`
+	NumFormat     int     `description:"数值格式 1:百分比 2:小数"`
+	IsConnected   int     `description:"是否连接 0不连接 1连接"`
+	LineColor     string  `description:"线条颜色"`
+	LineWidth     float64 `description:"线条宽度"`
+	LineStyle     string  `description:"线条样式"`
+	IsShow        bool    `description:"是否显示"`
+	IsAdd         bool    `description:"是否添加"`
+}
+
+// 自定义同期上下限
+type MaxMinLimits struct {
+	Color  string `description:"颜色"`
+	Year   int    `description:"上下限取值范围"`
+	Legend string `description:"图例名称"`
+	IsShow bool   `description:"是否显示"`
+	IsAdd  bool   `description:"是否添加"`
+}
+
+// 自定义同期均线
+type SamePeriodAverage struct {
+	Color     string  `description:"颜色"`
+	Year      int     `description:"均线取值范围"`
+	Legend    string  `description:"图例名称"`
+	LineType  string  `description:"线型"`
+	LineWidth float64 `description:"线宽"`
+	IsShow    bool    `description:"是否显示"`
+	IsAdd     bool    `description:"是否添加"`
+}
+
+// 自定义同期均线
+type SamePeriodAverageResp struct {
+	Color     string                   `description:"颜色"`
+	Year      int                      `description:"均线取值范围"`
+	Legend    string                   `description:"图例名称"`
+	LineType  string                   `description:"线型"`
+	LineWidth float64                  `description:"线宽"`
+	IsShow    bool                     `description:"是否显示"`
+	List      []*SamePeriodAverageData `description:"自定义均线列表"`
+	IsAdd     bool                     `description:"是否添加"`
+}
+
+type SamePeriodAverageData struct {
+	DataTime      string  `description:"数据日期"`
+	DataTimestamp int64   `description:"数据日期时间戳"`
+	Value         float64 `description:"均值"`
+}
+
+// 自定义同期标准差
+type SamePeriodStandardDeviation struct {
+	Color    string  `description:"颜色"`
+	Year     int     `description:"标准差取值范围"`
+	Legend   string  `description:"图例名称"`
+	Multiple float64 `description:"标准差倍数"`
+	IsShow   bool    `description:"是否显示"`
+	IsAdd    bool    `description:"是否添加"`
+}
+
+type SamePeriodStandardDeviationResp struct {
+	Color    string              `description:"颜色"`
+	Year     int                 `description:"标准差取值范围"`
+	Legend   string              `description:"图例名称"`
+	Multiple float64             `description:"标准差倍数"`
+	IsShow   bool                `description:"是否显示"`
+	List     []*MaxMinLimitsData `description:"自定义标准差列表"`
+	IsAdd    bool                `description:"是否添加"`
+}
+
+type SeasonChartResp struct {
+	MaxMinLimits                MaxMinLimitsResp                `description:"自定义上下限"`
+	SamePeriodAverage           SamePeriodAverageResp           `description:"自定义同期均线"`
+	SamePeriodStandardDeviation SamePeriodStandardDeviationResp `description:"自定义同期标准差线"`
+	RightAxis                   SeasonRightAxisResp             `description:"自定义右轴指标"`
+}
+
+// 自定义右轴指标
+type SeasonRightAxisResp struct {
+	SeasonRightAxis
+	EdbInfoList []*ChartEdbInfoMapping
+}
+
+type MaxMinLimitsResp struct {
+	List   []*MaxMinLimitsData `description:"自定义上下限列表"`
+	Color  string              `description:"颜色"`
+	Year   int                 `description:"上下限取值范围"`
+	Legend string              `description:"图例名称"`
+	IsShow bool                `description:"是否显示"`
+	IsAdd  bool                `description:"是否添加"`
+}
+
+type MaxMinLimitsData struct {
+	DataTime      string  `description:"数据日期"`
+	DataTimestamp int64   `description:"数据日期时间戳"`
+	MaxValue      float64 `description:"最大值"`
+	MinValue      float64 `description:"最小值"`
+}

+ 164 - 0
models/data_manage/chart_info_correlation.go

@@ -25,6 +25,7 @@ type ChartInfoCorrelation struct {
 	CorrelationData        string    `description:"Y轴-相关性系数"`
 	CreateTime             time.Time `description:"创建时间"`
 	ModifyTime             time.Time `description:"更新时间"`
+	AnalysisMode           int       `description:"分析模式: 0-单因子; 1-多因子"`
 }
 
 type CorrelationInfo struct {
@@ -38,6 +39,7 @@ type CorrelationInfo struct {
 	EdbInfoIdSecond int    `description:"B指标ID"`
 	PeriodData      string `description:"X轴-期数数据"`
 	CorrelationData string `description:"Y轴-相关性系数"`
+	AnalysisMode    int    `description:"分析模式: 0-单因子; 1-多因子"`
 }
 
 func (m *ChartInfoCorrelation) TableName() string {
@@ -134,3 +136,165 @@ func CreateCorrelationChartAndEdb(chartInfo *ChartInfo, edbMappingList []*ChartE
 	}
 	return
 }
+
+// FactorCorrelationConfig 因子指标系列-相关性配置
+type FactorCorrelationConfig struct {
+	LeadValue      int                       `description:"领先期数"`
+	LeadUnit       string                    `description:"频度"`
+	CalculateValue int                       `description:"计算窗口"`
+	CalculateUnit  string                    `description:"计算频度"`
+	SeriesEdb      []CorrelationSeriesEdbReq `description:"关联系列指标"`
+}
+
+// CorrelationChartLegend 相关性图表图例
+type CorrelationChartLegend struct {
+	LegendName string `description:"图例名称"`
+	Color      string `description:"图例颜色"`
+	EdbInfoId  int    `description:"指标ID"`
+	SeriesId   int    `description:"因子指标系列ID"`
+}
+
+// CorrelationSeriesEdbReq 指标系列
+type CorrelationSeriesEdbReq struct {
+	EdbInfoId int `description:"指标ID"`
+	SeriesId  int `description:"因子指标系列ID"`
+}
+
+// CorrelationChartInfoExtraConfig 相关性图表额外设置
+type CorrelationChartInfoExtraConfig struct {
+	LegendConfig []*CorrelationChartLegend `description:"图例设置"`
+}
+
+// CreateMultiFactorCorrelationChartAndEdb 新增多因子相关性图表
+func CreateMultiFactorCorrelationChartAndEdb(chartInfo *ChartInfo, edbMappingList []*ChartEdbMapping, correlationInfo *ChartInfoCorrelation, seriesMappings []*FactorEdbSeriesChartMapping) (chartInfoId int, err error) {
+	o := orm.NewOrmUsingDB("data")
+	tx, e := o.Begin()
+	if e != nil {
+		err = fmt.Errorf("orm begin err: %v", e)
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = tx.Rollback()
+			return
+		}
+		_ = tx.Commit()
+	}()
+
+	// 新增图表信息
+	chartId, e := tx.Insert(chartInfo)
+	if e != nil {
+		err = fmt.Errorf("chart insert err: %v", e)
+		return
+	}
+	chartInfo.ChartInfoId = int(chartId)
+	chartInfoId = chartInfo.ChartInfoId
+
+	// 指标mapping
+	if len(edbMappingList) > 0 {
+		for i := range edbMappingList {
+			edbMappingList[i].ChartInfoId = chartInfoId
+		}
+		_, e = tx.InsertMulti(200, edbMappingList)
+		if e != nil {
+			err = fmt.Errorf("edb mappings insert err: %v", e)
+			return
+		}
+	}
+
+	// 相关性信息
+	correlationInfo.CorrelationChartInfoId = chartInfoId
+	if _, e = tx.Insert(correlationInfo); e != nil {
+		err = fmt.Errorf("correlate chart insert err: %v", e)
+		return
+	}
+
+	// 指标系列-图表关联
+	if len(seriesMappings) > 0 {
+		for _, v := range seriesMappings {
+			v.ChartInfoId = chartInfoId
+		}
+		if _, e = tx.InsertMulti(200, seriesMappings); e != nil {
+			err = fmt.Errorf("series chart mappings insert err: %v", e)
+			return
+		}
+	}
+	return
+}
+
+// UpdateMultiFactorCorrelationChartAndEdb 编辑多因子相关性图表
+func UpdateMultiFactorCorrelationChartAndEdb(chartInfo *ChartInfo, edbMappingList []*ChartEdbMapping, correlationInfo *ChartInfoCorrelation, seriesMappings []*FactorEdbSeriesChartMapping, chartUpdateCols, correlateUpdateCols []string) (err error) {
+	o := orm.NewOrmUsingDB("data")
+	tx, e := o.Begin()
+	if e != nil {
+		err = fmt.Errorf("orm begin err: %v", e)
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = tx.Rollback()
+			return
+		}
+		_ = tx.Commit()
+	}()
+
+	// 更新图表信息
+	_, e = tx.Update(chartInfo, chartUpdateCols...)
+	if e != nil {
+		err = fmt.Errorf("chart update err: %v", e)
+		return
+	}
+
+	// 指标mapping
+	sql := `DELETE FROM chart_edb_mapping WHERE chart_info_id = ?`
+	_, e = tx.Raw(sql, chartInfo.ChartInfoId).Exec()
+	if e != nil {
+		err = fmt.Errorf("clear chart edb mapping err: %v", e)
+		return
+	}
+	if len(edbMappingList) > 0 {
+		for i := range edbMappingList {
+			edbMappingList[i].ChartInfoId = chartInfo.ChartInfoId
+		}
+		_, e = tx.InsertMulti(200, edbMappingList)
+		if e != nil {
+			err = fmt.Errorf("edb mappings insert err: %v", e)
+			return
+		}
+	}
+
+	// 相关性信息
+	_, e = tx.Update(correlationInfo, correlateUpdateCols...)
+	if e != nil {
+		err = fmt.Errorf("correlate chart update err: %v", e)
+		return
+	}
+
+	// 指标系列-图表关联
+	sql = `DELETE FROM factor_edb_series_chart_mapping WHERE chart_info_id = ?`
+	_, e = tx.Raw(sql, chartInfo.ChartInfoId).Exec()
+	if e != nil {
+		err = fmt.Errorf("clear chart series mapping err: %v", e)
+		return
+	}
+	if len(seriesMappings) > 0 {
+		for _, v := range seriesMappings {
+			v.ChartInfoId = chartInfo.ChartInfoId
+		}
+		if _, e = tx.InsertMulti(200, seriesMappings); e != nil {
+			err = fmt.Errorf("series chart mappings insert err: %v", e)
+			return
+		}
+	}
+	return
+}
+
+// FactorCorrelationEditDetail 编辑页详情
+type FactorCorrelationEditDetail struct {
+	ChartInfoId       int                                    `description:"图表ID"`
+	UniqueCode        string                                 `description:"图表唯一编码"`
+	BaseEdbInfo       *ChartEdbInfoMapping                   `description:"标的指标信息"`
+	EdbSeries         []*FactorEdbSeriesDetail               `description:"指标系列"`
+	CorrelationConfig CorrelationConfig                      `description:"相关性基础配置"`
+	CorrelationMatrix []FactorEdbSeriesCorrelationMatrixItem `description:"相关性矩阵"`
+}

+ 85 - 0
models/data_manage/chart_theme/request/theme.go

@@ -28,3 +28,88 @@ type SetDefaultThemeReq struct {
 	ChartThemeId     int `description:"主题id"`
 	ChartThemeTypeId int `description:"主题类型id"`
 }
+
+
+type ColorsOptions []string
+
+type LegendOptions struct {
+	VerticalAlign string `json:"verticalAlign"`
+	ItemStyle     struct {
+		Color        string `json:"color"`
+		FontSize     int    `json:"fontSize"`
+		Cursor       string `json:"cursor"`
+		FontWeight   string `json:"fontWeight"`
+		TextOverflow string `json:"textOverflow"`
+	} `json:"itemStyle"`
+}
+
+type TitleOptions struct {
+	Align string `json:"align"`
+	Style struct {
+		Color    string `json:"color"`
+		FontSize int    `json:"fontSize"`
+	} `json:"style"`
+}
+
+type MarkerOptions struct {
+	Style struct {
+		Color    string `json:"color"`
+		FontSize int    `json:"fontSize"`
+	} `json:"style"`
+}
+
+type AxisOptions struct {
+	Style struct {
+		Color    string `json:"color"`
+		FontSize int    `json:"fontSize"`
+	} `json:"style"`
+}
+
+type DrawOption struct {
+	PlotBackgroundColor string `json:"plotBackgroundColor"`
+}
+
+type LineOptions struct {
+	DashStyle string  `json:"dashStyle"`
+	LineWidth int     `json:"lineWidth"`
+	LineType  string  `json:"lineType"`
+	Radius    float64 `json:"radius"`
+}
+
+type OldChartOptions struct {
+	ColorsOptions  []string         `json:"colorsOptions"`
+	LineOptions    LineOptions      `json:"lineOptions"`
+	LegendOptions  interface{}      `json:"legendOptions"`
+	TitleOptions   interface{}      `json:"titleOptions"`
+	MarkerOptions  interface{}      `json:"markerOptions"`
+	XAxisOptions   interface{}      `json:"xAxisOptions"`
+	YAxisOptions   interface{}      `json:"yAxisOptions"`
+	DrawOption     interface{}      `json:"drawOption"`
+	LineOptionList []LineStyleOptions `json:"lineOptionList"`
+}
+
+type NewChartOptions struct {
+	OldChartOptions
+	LineOptionList []NewLineOptions `json:"lineOptionList"`
+}
+
+type NewLineOptions struct {
+	LineOptions
+	Color     string `json:"color"`
+	DataMark  string `json:"dataMark"`
+	MarkType  string `json:"markType"`
+	MarkSize  int    `json:"markSize"`
+	MarkColor string `json:"markColor"`
+}
+
+type LineStyleOptions struct {
+	DashStyle string `json:"dashStyle"`
+	Color     string `json:"color"`
+	LineWidth int    `json:"lineWidth"`
+	LineType  string `json:"lineType"`
+	Radius    int `json:"radius"`
+	DataMark  string `json:"dataMark"`
+	MarkType  string `json:"markType"`
+	MarkSize  int `json:"markSize"`
+	MarkColor string `json:"markColor"`
+}

+ 107 - 24
models/data_manage/edb_data_base.go

@@ -1,13 +1,15 @@
 package data_manage
 
 import (
+	"eta/eta_mobile/models/mgo"
 	"eta/eta_mobile/utils"
 	"fmt"
 	"github.com/beego/beego/v2/client/orm"
+	"go.mongodb.org/mongo-driver/bson"
 	"time"
 )
 
-// 指标数据->存储表
+// GetEdbDataTableName 指标数据->存储表
 func GetEdbDataTableName(source, subSource int) (tableName string) {
 	switch source {
 	case utils.DATA_SOURCE_THS:
@@ -155,7 +157,7 @@ func GetEdbDataTableName(source, subSource int) (tableName string) {
 		tableName = "edb_data_predict_ccalculate_standard_deviation"
 	case utils.DATA_SOURCE_PREDICT_CALCULATE_PERCENTILE: //预测百分位->70
 		tableName = "edb_data_predict_ccalculate_percentile"
-	case utils.DATA_SOURCE_FUBAO: //富宝数据 -> 71
+	case utils.DATA_SOURCE_FUBAO: //富宝-71
 		tableName = "edb_data_fubao"
 	case utils.DATA_SOURCE_CALCULATE_ZSXY:
 		tableName = "edb_data_calculate_zsxy" // 指数修匀->72
@@ -165,7 +167,9 @@ func GetEdbDataTableName(source, subSource int) (tableName string) {
 		tableName = "edb_data_calculate_zdyfx" // 自定义分析->74
 	case utils.DATA_SOURCE_CALCULATE_RJZ: //日均值->75
 		tableName = "edb_data_calculate_rjz"
-	case utils.DATA_SOURCE_ICPI: //icpi->79
+	case utils.DATA_SOURCE_GFEX: //广州期货交易所->78
+		tableName = "edb_data_gz"
+	case utils.DATA_SOURCE_ICPI: //ICPI消费价格指数->79
 		tableName = "edb_data_icpi"
 	default:
 		edbSource := EdbSourceIdMap[source]
@@ -176,6 +180,31 @@ func GetEdbDataTableName(source, subSource 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
@@ -189,6 +218,15 @@ type EdbDataBase struct {
 }
 
 func GetEdbDataAllByEdbCode(edbCode string, source, subSource, limit int) (items []*EdbInfoSearchData, err error) {
+	// 自有数据需要额外处理(从mongo获取)
+	if source == utils.DATA_SOURCE_BUSINESS && utils.UseMongo {
+		return GetEdbDataAllByEdbCodeByMongo(edbCode, source, subSource, limit)
+	}
+
+	return GetEdbDataAllByEdbCodeByMysql(edbCode, source, subSource, limit)
+}
+
+func GetEdbDataAllByEdbCodeByMysql(edbCode string, source, subSource, limit int) (items []*EdbInfoSearchData, err error) {
 	var pars []interface{}
 	pars = append(pars, edbCode)
 	o := orm.NewOrmUsingDB("data")
@@ -204,15 +242,58 @@ func GetEdbDataAllByEdbCode(edbCode string, source, subSource, limit int) (items
 	return
 }
 
-func GetEdbDataBaseByCodeAndDate(source, subSource int, edbCode string, startDate string) (count int, err error) {
+func GetEdbDataAllByEdbCodeByMongo(edbCode string, source, subSource, limit int) (list []*EdbInfoSearchData, err error) {
+	list = make([]*EdbInfoSearchData, 0)
+
+	mogDataObj := mgo.EdbDataBusiness{}
+	// 构建查询条件
+	queryConditions := bson.M{
+		"edb_code": edbCode,
+	}
+
+	var tmpDataList []*mgo.EdbDataBusiness
+	// 获取列表数据
+	if limit > 0 {
+		tmpDataList, err = mogDataObj.GetLimitDataList(queryConditions, int64(limit), []string{"-data_time"})
+	} else {
+		tmpDataList, err = mogDataObj.GetLimitDataList(queryConditions, int64(limit), []string{"-data_time"})
+	}
+	if err != nil {
+		return
+	}
+	for _, v := range tmpDataList {
+		list = append(list, &EdbInfoSearchData{
+			DataTime: v.DataTime.Format(utils.FormatDate),
+			Value:    v.Value,
+		})
+	}
+	return
+}
+
+func GetBaseIndexInfoByEdbCode(edbCode string, source int) (item *BaseIndexInfo, err error) {
+	var pars []interface{}
+	pars = append(pars, edbCode)
 	o := orm.NewOrmUsingDB("data")
-	tableName := GetEdbDataTableName(source, subSource)
-	sql := ` SELECT COUNT(1) AS count FROM %s WHERE edb_code=? AND data_time=? `
+
+	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, edbCode, startDate).QueryRow(&count)
+	err = o.Raw(sql, pars).QueryRow(&item)
 	return
 }
 
+func GetBaseIndexTableName(source int) (tableName string) {
+	edbSource := EdbSourceIdMap[source]
+	if edbSource != nil {
+		tableName = edbSource.IndexTableName
+	}
+	return
+}
 func GetEdbDataAllByEdbCodeAndSubSource(edbCode string, source, subSource, limit int) (items []*EdbInfoSearchData, err error) {
 	var pars []interface{}
 	pars = append(pars, edbCode)
@@ -229,7 +310,7 @@ func GetEdbDataAllByEdbCodeAndSubSource(edbCode string, source, subSource, limit
 	return
 }
 
-// GetEdbDataTableName 指标数据->存储表
+// GetEdbDataTableNameAndSubSource 指标数据->存储表
 func GetEdbDataTableNameAndSubSource(source, subSource int) (tableName string) {
 	switch source {
 	case utils.DATA_SOURCE_WIND:
@@ -244,6 +325,8 @@ func GetEdbDataTableNameAndSubSource(source, subSource int) (tableName string) {
 		} else {
 			tableName = "edb_data_ths_ds"
 		}
+	case utils.DATA_SOURCE_YS:
+		tableName = "edb_data_ys"
 	default:
 		edbSource := EdbSourceIdMap[source]
 		if edbSource != nil {
@@ -253,26 +336,26 @@ func GetEdbDataTableNameAndSubSource(source, subSource int) (tableName string) {
 	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) {
+func GetEdbDataAllByEdbCodes(edbCodes []string, limit int) (items []*EdbInfoSearchData, err error) {
 	var pars []interface{}
-	pars = append(pars, edbCode)
+	pars = append(pars, edbCodes)
 	o := orm.NewOrmUsingDB("data")
 
-	tableName := GetBaseIndexTableName(source)
-	if tableName == "" {
-		err = fmt.Errorf("未找到对应的表")
-		return
+	sql := ` SELECT * FROM edb_data_ys WHERE edb_code IN (` + utils.GetOrmInReplace(len(edbCodes)) + `) ORDER BY data_time DESC`
+	if limit > 0 {
+		sql += `  LIMIT ?  `
+		pars = append(pars, limit)
 	}
-	sql := ` SELECT * FROM %s WHERE index_code=? `
+	_, err = o.Raw(sql, pars).QueryRows(&items)
+	return
+}
 
-	sql = fmt.Sprintf(sql, tableName)
-	err = o.Raw(sql, pars).QueryRow(&item)
+func GetAddSql(edbInfoId, edbCode, dataTime, timestampStr string, value string) (addSql string) {
+	nowStr := time.Now().Format(utils.FormatDateTime)
+	addSql += "("
+	addSql += edbInfoId + "," + "'" + edbCode + "'" + "," + "'" + dataTime + "'" + "," + value + "," + "'" + nowStr + "'" +
+		"," + "'" + nowStr + "'" + "," + "1"
+	addSql += "," + "'" + timestampStr + "'"
+	addSql += "),"
 	return
 }

+ 0 - 174
models/data_manage/edb_data_calculate.go

@@ -1,174 +0,0 @@
-package data_manage
-
-import (
-	"errors"
-	"eta/eta_mobile/utils"
-	"fmt"
-	"github.com/beego/beego/v2/client/orm"
-	"github.com/yidane/formula"
-	"strconv"
-	"strings"
-	"time"
-)
-
-type EdbDataCalculate struct {
-	EdbDataId     int `orm:"column(edb_data_id);pk"`
-	EdbInfoId     int
-	EdbCode       string
-	DataTime      string
-	Value         float64
-	Status        int
-	CreateTime    time.Time
-	ModifyTime    time.Time
-	DataTimestamp int64
-}
-
-func AddEdbDataCalculate(items []*EdbDataCalculate) (err error) {
-	o := orm.NewOrmUsingDB("data")
-	_, err = o.InsertMulti(1, items)
-	return
-}
-
-func AddEdbDataCalculateBySql(sqlStr string) (err error) {
-	o := orm.NewOrmUsingDB("data")
-	_, err = o.Raw(sqlStr).Exec()
-	return
-}
-
-func ModifyEdbDataCalculate(edbInfoId int64, dataTime string, value float64) (err error) {
-	o := orm.NewOrmUsingDB("data")
-	sql := ` UPDATE edb_data_calculate SET value=?,modify_time=NOW() WHERE edb_info_id=? AND data_time=? `
-	_, err = o.Raw(sql, value, edbInfoId, dataTime).Exec()
-	return
-}
-
-func GetEdbDataCalculateByCodeAndDate(edbCode string, startDate string) (count int, err error) {
-	o := orm.NewOrmUsingDB("data")
-	sql := ` SELECT COUNT(1) AS count FROM edb_data_calculate WHERE edb_code=? AND data_time=? `
-	err = o.Raw(sql, edbCode, startDate).QueryRow(&count)
-	return
-}
-
-// 刷新全部数据
-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 {
-		return
-	}
-	defer func() {
-		if err != nil {
-			_ = to.Rollback()
-		} else {
-			_ = to.Commit()
-		}
-	}()
-	fmt.Println(startDate, endDate)
-	saveDataMap := make(map[string]map[int]float64)
-	for _, v := range edbInfoIdArr {
-		var condition string
-		var pars []interface{}
-		condition += " AND edb_info_id=? "
-		pars = append(pars, v.EdbInfoId)
-		if startDate != "" {
-			condition += " AND data_time>=? "
-			pars = append(pars, startDate)
-		}
-		if endDate != "" {
-			condition += " AND data_time<=? "
-			pars = append(pars, endDate)
-		}
-		fmt.Println("v.Source:", v.Source)
-		dataList, err := GetEdbDataListAll(condition, pars, v.Source, v.SubSource, 1)
-		if err != nil {
-			return 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 `
-	var isAdd bool
-
-	//获取指标所有数据
-	dataList := make([]*EdbDataBase, 0)
-	dataTableName := GetEdbDataTableName(source, subSource)
-	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
-	}
-	edbInfoIdStr := strconv.Itoa(edbInfoId)
-	existDataMap := make(map[string]string)
-	for sk, sv := range saveDataMap {
-		fmt.Println(sk, sv)
-		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
-			}
-
-			saveValue := utils.SubFloatToString(calVal, 4)
-			if existVal, ok := dataMap[sk]; !ok {
-				dataTime, _ := time.Parse(utils.FormatDate, sk)
-				timestamp := dataTime.UnixNano() / 1e6
-				timeStr := fmt.Sprintf("%d", timestamp)
-
-				if _, existOk := existDataMap[sk]; !existOk {
-					addSql += GetAddSql(edbInfoIdStr, edbCode, sk, timeStr, saveValue)
-					isAdd = true
-				}
-				existDataMap[sk] = sk
-			} 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, saveValue, edbInfoId, sk).Exec()
-					if err != nil {
-						return err
-					}
-				}
-			}
-		}
-	}
-	if isAdd {
-		addSql = strings.TrimRight(addSql, ",")
-		_, err = to.Raw(addSql).Exec()
-		if err != nil {
-			fmt.Println("RefreshAllCalculate add Err", err.Error())
-			return
-		}
-	}
-	return
-}

+ 0 - 27
models/data_manage/edb_data_calculate_ljztbpj.go

@@ -1,27 +0,0 @@
-package data_manage
-
-import (
-	"github.com/beego/beego/v2/client/orm"
-	"time"
-)
-
-// EdbDataCalculateLjztbpj 累计值同比拼接数据结构体
-type EdbDataCalculateLjztbpj struct {
-	EdbDataId     int `orm:"column(edb_data_id);pk"`
-	EdbInfoId     int
-	EdbCode       string
-	DataTime      string
-	Value         float64
-	Status        int
-	CreateTime    time.Time
-	ModifyTime    time.Time
-	DataTimestamp int64
-}
-
-// GetAllEdbDataCalculateLjztbpjByEdbInfoId 根据指标id获取全部的数据
-func GetAllEdbDataCalculateLjztbpjByEdbInfoId(edbInfoId int) (items []*EdbDataCalculateLjztbpj, err error) {
-	o := orm.NewOrmUsingDB("data")
-	sql := ` SELECT * FROM edb_data_calculate_ljztbpj WHERE edb_info_id=? ORDER BY data_time DESC `
-	_, err = o.Raw(sql, edbInfoId).QueryRows(&items)
-	return
-}

+ 0 - 160
models/data_manage/edb_data_calculate_time_shift.go

@@ -1,160 +0,0 @@
-package data_manage
-
-import (
-	"errors"
-	"eta/eta_mobile/utils"
-	"fmt"
-	"github.com/beego/beego/v2/client/orm"
-	"github.com/shopspring/decimal"
-	"strconv"
-	"strings"
-	"time"
-)
-
-// 时间移位
-func EditCalculateTimeShift(req *EdbInfoCalculateBatchEditReq, fromEdbInfo *EdbInfo, edbCode string, oldEdbInfo *EdbInfo) (edbInfoId int, err error) {
-	edbInfoId = req.EdbInfoId
-	o := orm.NewOrmUsingDB("data")
-	to, err := o.Begin()
-	if err != nil {
-		return
-	}
-	defer func() {
-		if err != nil {
-			_ = to.Rollback()
-		} else {
-			_ = to.Commit()
-		}
-	}()
-
-	//修改指标信息
-	sql := ` UPDATE  edb_info
-			SET
-			  edb_name =?,
-			  edb_name_source=?,
-			  frequency = ?,
-			  unit = ?,
-			  classify_id = ?,
-			  move_type=?,
-			  move_frequency=?,
-			  calculate_formula=?,
-			  modify_time = NOW()
-			WHERE edb_info_id = ? `
-	_, err = to.Raw(sql, req.EdbName, req.EdbName, req.Frequency, req.Unit, req.ClassifyId, req.MoveType, req.MoveFrequency, req.Formula, edbInfoId).Exec()
-	if err != nil {
-		return
-	}
-
-	var existCondition string
-	var existPars []interface{}
-	existCondition += " AND edb_info_id=? "
-	existPars = append(existPars, edbInfoId)
-
-	existCondition += " AND from_edb_info_id=? "
-	existPars = append(existPars, req.FromEdbInfoId)
-
-	//判断计算指标是否被更换
-	count, err := GetEdbInfoCalculateCountByCondition(req.Source, existCondition, existPars)
-	if err != nil {
-		err = errors.New("判断指标是否改变失败,Err:" + err.Error())
-		return
-	}
-	if count <= 0 || req.MoveType != oldEdbInfo.MoveType || req.MoveFrequency != oldEdbInfo.MoveFrequency || req.Formula != oldEdbInfo.CalculateFormula {
-		if count <= 0 {
-			//删除,计算指标关联的,基础指标的关联关系
-			sql = ` DELETE FROM edb_info_calculate_mapping WHERE edb_info_id = ? `
-			_, err = to.Raw(sql, edbInfoId).Exec()
-			if err != nil {
-				err = errors.New("删除计算指标关联关系失败,Err:" + err.Error())
-				return
-			}
-			//关联关系
-			{
-				calculateMappingItem := new(EdbInfoCalculateMapping)
-				calculateMappingItem.CreateTime = time.Now()
-				calculateMappingItem.ModifyTime = time.Now()
-				calculateMappingItem.Sort = 1
-				calculateMappingItem.EdbCode = edbCode
-				calculateMappingItem.EdbInfoId = edbInfoId
-				calculateMappingItem.FromEdbInfoId = fromEdbInfo.EdbInfoId
-				calculateMappingItem.FromEdbCode = fromEdbInfo.EdbCode
-				calculateMappingItem.FromEdbName = fromEdbInfo.EdbName
-				calculateMappingItem.FromSource = fromEdbInfo.Source
-				calculateMappingItem.FromSourceName = fromEdbInfo.SourceName
-				calculateMappingItem.FromTag = ""
-				calculateMappingItem.Source = utils.DATA_SOURCE_CALCULATE_TIME_SHIFT
-				calculateMappingItem.SourceName = "时间移位"
-				_, err = to.Insert(calculateMappingItem)
-				if err != nil {
-					return
-				}
-			}
-		}
-		//清空原有数据
-		sql = ` DELETE FROM edb_data_calculate_time_shift WHERE edb_info_id = ? `
-		_, err = to.Raw(sql, edbInfoId).Exec()
-		if err != nil {
-			return edbInfoId, err
-		}
-
-		edbInfoIdStr := strconv.Itoa(edbInfoId)
-
-		var shiftDay int
-		formulaInt, _ := strconv.Atoi(req.Formula)
-		switch req.MoveFrequency {
-		case "天":
-			shiftDay = formulaInt
-		case "周":
-			shiftDay = formulaInt * 7
-		case "月":
-			shiftDay = formulaInt * 30
-		case "季":
-			shiftDay = formulaInt * 90
-		case "年":
-			shiftDay = formulaInt * 365
-		default:
-			shiftDay = formulaInt
-		}
-
-		//计算数据
-		var condition string
-		var pars []interface{}
-		condition += " AND edb_info_id=? "
-		pars = append(pars, req.FromEdbInfoId)
-		fmt.Println("EdbInfoId:", req.FromEdbInfoId)
-		dataList, err := GetEdbDataListAll(condition, pars, fromEdbInfo.Source, fromEdbInfo.SubSource, 0)
-		if err != nil {
-			return edbInfoId, err
-		}
-		addSql := ` INSERT INTO edb_data_calculate_time_shift(edb_info_id,edb_code,data_time,value,create_time,modify_time,status,data_timestamp) values `
-		var isAdd bool
-		existMap := make(map[string]string)
-		dataLen := len(dataList)
-		if req.MoveType == 2 {
-			shiftDay = -shiftDay
-		}
-		for i := 0; i < dataLen; i++ {
-			//当期
-			currentItem := dataList[i]
-			currentDate, _ := time.Parse(utils.FormatDate, currentItem.DataTime)
-			newDate := currentDate.AddDate(0, 0, shiftDay)
-			existKey := edbCode + newDate.Format(utils.FormatDate)
-			if _, ok := existMap[existKey]; !ok {
-				timestamp := newDate.UnixNano() / 1e6
-				timestampStr := fmt.Sprintf("%d", timestamp)
-				valStr := decimal.NewFromFloat(currentItem.Value).String()
-				addSql += GetAddSql(edbInfoIdStr, edbCode, newDate.Format(utils.FormatDate), timestampStr, valStr)
-				isAdd = true
-			}
-			existMap[existKey] = currentItem.DataTime
-		}
-		if isAdd {
-			addSql = strings.TrimRight(addSql, ",")
-			_, err = to.Raw(addSql).Exec()
-			if err != nil {
-				return edbInfoId, err
-			}
-		}
-	}
-	return
-}

+ 0 - 34
models/data_manage/edb_data_calculate_zjpj.go

@@ -1,34 +0,0 @@
-package data_manage
-
-import (
-	"github.com/beego/beego/v2/client/orm"
-	"time"
-)
-
-// EdbDataCalculateZjpj 直接拼接数据结构体
-type EdbDataCalculateZjpj struct {
-	EdbDataId     int `orm:"column(edb_data_id);pk"`
-	EdbInfoId     int
-	EdbCode       string
-	DataTime      string
-	Value         float64
-	Status        int
-	CreateTime    time.Time
-	ModifyTime    time.Time
-	DataTimestamp int64
-}
-
-// GetAllEdbDataCalculateZjpjByEdbInfoId 根据指标id获取全部的数据
-func GetAllEdbDataCalculateZjpjByEdbInfoId(edbInfoId int) (items []*EdbDataCalculateZjpj, err error) {
-	o := orm.NewOrmUsingDB("data")
-	sql := ` SELECT * FROM edb_data_calculate_zjpj WHERE edb_info_id=? ORDER BY data_time DESC `
-	_, err = o.Raw(sql, edbInfoId).QueryRows(&items)
-	return
-}
-
-type EdbDataFromZjpj struct {
-	Date   map[string]int64   `json:"date"`
-	Ticker map[string]string  `json:"ticker"`
-	Field  map[string]string  `json:"field"`
-	Value  map[string]float64 `json:"value"`
-}

+ 0 - 347
models/data_manage/edb_data_cffex.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,304 +61,6 @@ func GetEdbDataCffexMaxOrMinDate(edbCode string) (minDate, maxDate string, err e
 	return
 }
 
-func GetEdbDataByCffex(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
-	cffexBaseDataAll, err := GetBaseFromCffexDataAllByIndexCode(edbCode, suffix)
-	if err != nil && err.Error() != utils.ErrNoRow() {
-		return
-	}
-
-	var isAdd bool
-	addSql := ` INSERT INTO edb_data_cffex(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 cffexBaseDataAll {
-		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_CFFEX, utils.DATA_SUB_SOURCE_EDB, size)
-	if err != nil {
-		utils.FileLogData.Info("GetEdbDataCffexByCode Err:%s", err.Error())
-		return searchItem, err
-	}
-	minDate, maxDate, err := GetEdbDataCffexMaxOrMinDate(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
-}
-
-// RefreshEdbDataByCffex 刷新中金所指标数据
-func RefreshEdbDataByCffex(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 := GetCffexDataByTradeCode(condition, pars)
-
-	addSql := ` INSERT INTO edb_data_cffex(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 := GetEdbDataCffexByCodeAndDate(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 = ModifyEdbDataCffex(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
-}
-
-// RefreshAllEdbDataByCffex 全部刷新中金所
-func RefreshAllEdbDataByCffex(edbInfoId, source, subSource 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()
-		}
-	}()
-	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 := GetCffexDataByTradeCode(condition, pars)
-
-	//获取指标所有数据
-	dataList := make([]*EdbDataBase, 0)
-	dataTableName := GetEdbDataTableName(source, subSource)
-	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_cffex(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
-}
-
 // GetBaseInfoFromCffexByIndexCode 获取指标信息
 func GetBaseInfoFromCffexByIndexCode(indexCode, suffix string) (list []*BaseInfoFromCffex, err error) {
 	o := orm.NewOrmUsingDB("data")
@@ -370,49 +69,3 @@ func GetBaseInfoFromCffexByIndexCode(indexCode, suffix string) (list []*BaseInfo
 	_, err = o.Raw(sql, indexCode).QueryRows(&list)
 	return
 }
-
-func GetCffexDataByTradeCode(condition string, pars []interface{}) (item []*BaseFromCffexDataSimple, err error) {
-	sql := ` SELECT * FROM base_from_trade_cffex_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 AddEdbDataCffexBySql(sqlStr string) (err error) {
-	o := orm.NewOrmUsingDB("data")
-	_, err = o.Raw(sqlStr).Exec()
-	return
-}
-
-func GetEdbDataCffexByCode(edbCode string) (items []*EdbInfoSearchData, err error) {
-	o := orm.NewOrmUsingDB("data")
-	sql := ` SELECT * FROM edb_data_cffex WHERE edb_code=? ORDER BY data_time DESC LIMIT ? `
-	_, err = o.Raw(sql, edbCode, utils.EDB_DATA_LIMIT).QueryRows(&items)
-	return
-}
-
-func GetBaseFromCffexDataAllByIndexCode(indexCode, suffix string) (list []*BaseFromTradeCFFEXIndex, err error) {
-	o := orm.NewOrmUsingDB("data")
-	sql := `SELECT * FROM base_from_trade_cffex_index WHERE %s_code=? `
-	sql = fmt.Sprintf(sql, suffix)
-	_, err = o.Raw(sql, indexCode).QueryRows(&list)
-	return
-}
-
-func GetEdbDataCffexByCodeAndDate(edbCode string, startDate string) (count int, err error) {
-	o := orm.NewOrmUsingDB("data")
-	sql := ` SELECT COUNT(1) AS count FROM edb_data_cffex WHERE edb_code=? AND data_time=? `
-	err = o.Raw(sql, edbCode, startDate).QueryRow(&count)
-	return
-}
-
-func ModifyEdbDataCffex(edbInfoId int64, dataTime, value string) (err error) {
-	o := orm.NewOrmUsingDB("data")
-	sql := ` UPDATE edb_data_cffex SET value=?,modify_time=NOW() WHERE edb_info_id=? AND data_time=? `
-	_, err = o.Raw(sql, value, edbInfoId, dataTime).Exec()
-	return
-}

+ 0 - 227
models/data_manage/edb_data_coal.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,204 +61,6 @@ func GetEdbDataCoalMaxOrMinDate(edbCode string) (minDate, maxDate string, err er
 	return
 }
 
-// RefreshEdbDataByCoal 刷新煤炭网指标数据
-func RefreshEdbDataByCoal(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()
-		}
-	}()
-	var suffix string
-	if strings.Contains(edbCode, "jsm") {
-		suffix = "jsm_index"
-	} else if strings.Contains(edbCode, "company") {
-		suffix = "company_index"
-	} else if strings.Contains(edbCode, "firm") {
-		suffix = "firm_index"
-	} else if strings.Contains(edbCode, "coastal") {
-		suffix = "coastal_index"
-	} else if strings.Contains(edbCode, "inland") {
-		suffix = "inland_index"
-	}
-	edbInfoIdStr := strconv.Itoa(edbInfoId)
-	//计算数据
-	var condition string
-	var pars []interface{}
-
-	if edbCode != "" {
-		condition += " AND index_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)
-	}
-
-	coalDataList, err := GetCoalDataByTradeCode(condition, suffix, pars)
-
-	addSql := ` INSERT INTO edb_data_coal(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 coalDataList {
-		item := v
-		itemValue := v.DealValue
-		if _, ok := existMap[v.DataTime]; !ok {
-			count, err := GetEdbDataCoalByCodeAndDate(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 = ModifyEdbDataCoal(int64(edbInfoId), v.DataTime, v.DealValue)
-				if err != nil {
-					return err
-				}
-			}
-		}
-		existMap[v.DataTime] = v.DealValue
-	}
-	if isAdd {
-		addSql = strings.TrimRight(addSql, ",")
-		_, err = to.Raw(addSql).Exec()
-		if err != nil {
-			return err
-		}
-	}
-	return
-}
-
-// RefreshAllEdbDataByCoal 全部刷新中金所
-func RefreshAllEdbDataByCoal(edbInfoId, source, subSource 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()
-		}
-	}()
-	var suffix string
-	if strings.Contains(edbCode, "jsm") {
-		suffix = "jsm_index"
-	} else if strings.Contains(edbCode, "company") {
-		suffix = "company_index"
-	} else if strings.Contains(edbCode, "firm") {
-		suffix = "firm_index"
-	} else if strings.Contains(edbCode, "coastal") {
-		suffix = "coastal_index"
-	} else if strings.Contains(edbCode, "inland") {
-		suffix = "inland_index"
-	}
-	edbInfoIdStr := strconv.Itoa(edbInfoId)
-	//计算数据
-	var condition string
-	var pars []interface{}
-
-	if edbCode != "" {
-		condition += " AND index_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)
-	}
-
-	coalDataList, err := GetCoalDataByTradeCode(condition, suffix, pars)
-
-	//获取指标所有数据
-	dataList := make([]*EdbDataBase, 0)
-	dataTableName := GetEdbDataTableName(source, subSource)
-	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_coal(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 coalDataList {
-		item := v
-		itemValue := v.DealValue
-		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
-}
-
 // GetBaseInfoFromCoalByIndexCode 获取指标信息
 func GetBaseInfoFromCoalByIndexCode(indexCode, suffix string) (list []*BaseInfoFromCoal, err error) {
 	o := orm.NewOrmUsingDB("data")
@@ -270,29 +69,3 @@ func GetBaseInfoFromCoalByIndexCode(indexCode, suffix string) (list []*BaseInfoF
 	_, err = o.Raw(sql, indexCode).QueryRows(&list)
 	return
 }
-
-func GetCoalDataByTradeCode(condition, suffix string, pars []interface{}) (item []*BaseFromCoalDataSimple, err error) {
-	sql := ` SELECT * FROM base_from_coalmine_%s WHERE 1=1 `
-	sql = fmt.Sprintf(sql, suffix)
-	o := orm.NewOrmUsingDB("data")
-	if condition != "" {
-		sql += condition
-	}
-	sql += ` ORDER BY data_time DESC `
-	_, err = o.Raw(sql, pars).QueryRows(&item)
-	return
-}
-
-func GetEdbDataCoalByCodeAndDate(edbCode string, startDate string) (count int, err error) {
-	o := orm.NewOrmUsingDB("data")
-	sql := ` SELECT COUNT(1) AS count FROM edb_data_coal WHERE edb_code=? AND data_time=? `
-	err = o.Raw(sql, edbCode, startDate).QueryRow(&count)
-	return
-}
-
-func ModifyEdbDataCoal(edbInfoId int64, dataTime, value string) (err error) {
-	o := orm.NewOrmUsingDB("data")
-	sql := ` UPDATE edb_data_coal SET value=?,modify_time=NOW() WHERE edb_info_id=? AND data_time=? `
-	_, err = o.Raw(sql, value, edbInfoId, dataTime).Exec()
-	return
-}

+ 1 - 54
models/data_manage/edb_data_fubao.go

@@ -2,65 +2,12 @@ package data_manage
 
 import (
 	"github.com/beego/beego/v2/client/orm"
-	"time"
 )
 
-//富宝数据
-
-type EdbDataFubao struct {
-	EdbDataId     int `orm:"column(edb_data_id);pk"`
-	EdbInfoId     int
-	EdbCode       string
-	DataTime      string
-	Value         float64
-	Status        int
-	CreateTime    time.Time
-	ModifyTime    time.Time
-	DataTimestamp int64
-}
-
-func AddEdbDataFubaoBySql(sqlStr string) (err error) {
-	o := orm.NewOrmUsingDB("data")
-	_, err = o.Raw(sqlStr).Exec()
-	return
-}
-
-func ModifyEdbDataFubao(edbInfoId int64, dataTime string, value float64) (err error) {
-	o := orm.NewOrmUsingDB("data")
-	sql := ` UPDATE edb_data_ths SET value=?,modify_time=NOW() WHERE edb_info_id=? AND data_time=? `
-	_, err = o.Raw(sql, value, edbInfoId, dataTime).Exec()
-	return
-}
-
+// 富宝数据
 func GetEdbDataFubaoMaxOrMinDate(edbCode string) (min_date, max_date string, err error) {
 	o := orm.NewOrmUsingDB("data")
 	sql := ` SELECT MIN(data_time) AS min_date,MAX(data_time) AS max_date FROM edb_data_ths WHERE edb_code=? `
 	err = o.Raw(sql, edbCode).QueryRow(&min_date, &max_date)
 	return
 }
-
-func GetEdbDataFubaoByCodeAndDate(edbCode string, startDate string) (count int, err error) {
-	o := orm.NewOrmUsingDB("data")
-	sql := ` SELECT COUNT(1) AS count FROM edb_data_ths WHERE edb_code=? AND data_time=? `
-	err = o.Raw(sql, edbCode, startDate).QueryRow(&count)
-	return
-}
-
-func GetEdbDataFubaoByCode(edbCode string, size int) (items []*EdbInfoSearchData, err error) {
-	o := orm.NewOrmUsingDB("data")
-	sql := ` SELECT * FROM edb_data_ths WHERE edb_code=? ORDER BY data_time DESC LIMIT ? `
-	_, err = o.Raw(sql, edbCode, size).QueryRows(&items)
-	return
-}
-
-type EdbDataFromFubao struct {
-	DataVol   int64       `json:"dataVol"`
-	Errmsg    string      `json:"errmsg"`
-	Errorcode int64       `json:"errorcode"`
-	Perf      interface{} `json:"perf"`
-	Tables    []struct {
-		ID    []string  `json:"id"`
-		Time  []string  `json:"time"`
-		Value []float64 `json:"value"`
-	} `json:"tables"`
-}

+ 161 - 4
models/data_manage/edb_data_insert_config.go

@@ -2,9 +2,12 @@ package data_manage
 
 import (
 	"errors"
+	"eta/eta_mobile/models/mgo"
 	"eta/eta_mobile/utils"
 	"fmt"
 	"github.com/beego/beego/v2/client/orm"
+	"go.mongodb.org/mongo-driver/bson"
+	"go.mongodb.org/mongo-driver/mongo"
 	"strconv"
 	"time"
 )
@@ -51,8 +54,6 @@ func CreateEdbDataInsertConfigAndData(edbInfo *EdbInfo, date time.Time, value st
 	}
 
 	dateStr := date.Format(utils.FormatDate)
-	timestamp := date.UnixNano() / 1e6
-	timeStr := fmt.Sprintf("%d", timestamp)
 
 	var saveValue string
 	if value != "" {
@@ -131,6 +132,55 @@ func CreateEdbDataInsertConfigAndData(edbInfo *EdbInfo, date time.Time, value st
 		}
 	}
 
+	// 指标明细数据更新
+	if edbInfo.Source == utils.DATA_SOURCE_BUSINESS && utils.UseMongo {
+		dateStr, err = updateInsertConfigValueByMongo(to, edbInfo, oldConfigDate, date, value)
+	} else {
+		dateStr, err = updateInsertConfigValueByMysql(to, edbInfo, oldConfigDate, date, value)
+	}
+	if err != nil {
+		return
+	}
+
+	// 指标信息更新
+	edbInfo.EndDate = dateStr
+	_, err = to.Update(edbInfo, "EndDate")
+
+	return
+}
+
+// updateInsertConfigValueByMysql
+// @Description: 从mysql更新或插入配置值
+// @author: Roc
+// @datetime 2024-05-09 11:05:41
+// @param to orm.TxOrmer
+// @param edbInfo *EdbInfo
+// @param oldConfigDate
+// @param date time.Time
+// @param value string
+// @return dateStr string
+// @return err error
+func updateInsertConfigValueByMysql(to orm.TxOrmer, edbInfo *EdbInfo, oldConfigDate, date time.Time, value string) (dateStr string, err error) {
+	tableName := GetEdbDataTableName(edbInfo.Source, edbInfo.SubSource)
+	if tableName == `` {
+		err = errors.New("找不到该指标的数据表")
+		return
+	}
+
+	dateStr = date.Format(utils.FormatDate)
+	timestamp := date.UnixNano() / 1e6
+	timeStr := fmt.Sprintf("%d", timestamp)
+	var saveValue string
+	if value != "" {
+		floatValue, e := strconv.ParseFloat(value, 64)
+		if e != nil {
+			err = e
+			fmt.Println("转换失败:", e.Error())
+			return
+		}
+		saveValue = utils.SubFloatToString(floatValue, 30)
+	}
+
 	var offsetDate string
 	// 更改数据
 	{
@@ -174,8 +224,115 @@ func CreateEdbDataInsertConfigAndData(edbInfo *EdbInfo, date time.Time, value st
 		}
 	}
 
-	edbInfo.EndDate = dateStr
-	_, err = to.Update(edbInfo, "EndDate")
+	return
+}
+
+// updateInsertConfigValueByMongo
+// @Description: 从mongo更新或插入配置值
+// @author: Roc
+// @datetime 2024-05-09 11:05:49
+// @param to orm.TxOrmer
+// @param edbInfo *EdbInfo
+// @param oldConfigDate
+// @param newDate time.Time
+// @param value string
+// @return dateStr string
+// @return err error
+func updateInsertConfigValueByMongo(to orm.TxOrmer, edbInfo *EdbInfo, oldConfigDate, newDate time.Time, value string) (dateStr string, err error) {
+	tableName := GetEdbDataTableName(edbInfo.Source, edbInfo.SubSource)
+	if tableName == `` {
+		err = errors.New("找不到该指标的数据表")
+		return
+	}
+
+	dateStr = newDate.Format(utils.FormatDate)
+	timestamp := newDate.UnixNano() / 1e6
+	var floatValue float64
+	if value != "" {
+		floatValue, err = strconv.ParseFloat(value, 64)
+		if err != nil {
+			fmt.Println("转换失败:", err.Error())
+			return
+		}
+	}
+
+	mogDataObj := mgo.EdbDataBusiness{}
+	coll := mogDataObj.GetCollection()
+
+	var edbDateData *mgo.EdbDataBusiness
+	if !oldConfigDate.IsZero() {
+		// 构建查询条件
+		queryConditions := bson.M{
+			"edb_info_id": edbInfo.EdbInfoId,
+			"data_time":   oldConfigDate,
+		}
+
+		edbDateData, err = mogDataObj.GetItem(queryConditions)
+		//if tmpErr != nil && tmpErr == mongo.ErrNoDocuments {
+		//	err = tmpErr
+		//	return
+		//}
+		if err != nil && err != mongo.ErrNoDocuments {
+			return
+		}
+		err = nil
+
+	}
+
+	// 如果是没有历史数据,那么就需要增加数据
+	if edbDateData == nil {
+		addDataItem := mgo.EdbDataBusiness{
+			//ID:            primitive.ObjectID{},
+			EdbInfoId:     edbInfo.EdbInfoId,
+			EdbCode:       edbInfo.EdbCode,
+			DataTime:      newDate,
+			Value:         floatValue,
+			CreateTime:    time.Now(),
+			ModifyTime:    time.Now(),
+			DataTimestamp: timestamp,
+		}
+		err = mogDataObj.InsertDataByColl(coll, addDataItem)
+		if err != nil {
+			fmt.Println("mogDataObj.BatchInsertData() Err:" + err.Error())
+			return
+		}
+		return
+	}
+
+	// 数据清空
+	if value == "" {
+		queryConditions := bson.M{
+			"edb_info_id": edbInfo.EdbInfoId,
+		}
+
+		// 获取最新的两条数据
+		tmpDataList, tmpErr := mogDataObj.GetLimitDataList(queryConditions, 2, []string{"-data_time"})
+		if tmpErr != nil {
+			fmt.Println("mogDataObj.GetLimitDataList() Err:" + tmpErr.Error())
+			return
+		}
+		// 如果并没有两条数据,那么就返回
+		if len(tmpDataList) < 2 {
+			return
+		}
+
+		// 实际应该是倒数第二条数据的日期
+		dateStr = tmpDataList[1].DataTime.Format(utils.FormatDate)
+
+		// 删除插入的数据
+		err = mogDataObj.RemoveManyByColl(coll, bson.M{"_id": tmpDataList[0].ID})
+
+		return
+	}
+
+	// 更新配置的数据
+	updateData := bson.M{"$set": bson.M{
+		"value":          floatValue,
+		"modify_time":    time.Now(),
+		"data_time":      newDate,
+		"data_timestamp": timestamp,
+	}}
+	err = mogDataObj.UpdateDataByColl(coll, bson.M{"_id": edbDateData.ID}, updateData)
 
 	return
 }

+ 0 - 315
models/data_manage/edb_data_lz.go

@@ -1,327 +1,12 @@
 package data_manage
 
 import (
-	"eta/eta_mobile/utils"
-	"fmt"
 	"github.com/beego/beego/v2/client/orm"
-	"strconv"
-	"strings"
-	"time"
 )
 
-func AddEdbDataLzBySql(sqlStr string) (err error) {
-	o := orm.NewOrmUsingDB("data")
-	_, err = o.Raw(sqlStr).Exec()
-	return
-}
-
-func GetEdbDataLzByEdbCode(edbCode string) (items []*EdbInfoSearchData, err error) {
-	o := orm.NewOrmUsingDB("data")
-	sql := ` SELECT * FROM edb_data_lz WHERE edb_code=? ORDER BY data_time DESC LIMIT ? `
-	_, err = o.Raw(sql, edbCode, utils.EDB_DATA_LIMIT).QueryRows(&items)
-	return
-}
-
 func GetEdbDataLzMaxOrMinDate(edbCode string) (min_date, max_date string, err error) {
 	o := orm.NewOrmUsingDB("data")
 	sql := ` SELECT MIN(data_time) AS min_date,MAX(data_time) AS max_date FROM edb_data_lz WHERE edb_code=? `
 	err = o.Raw(sql, edbCode).QueryRow(&min_date, &max_date)
 	return
 }
-
-type lzSurveyData struct {
-	DataTime   string `orm:"column(data_time)" description:"日期"`
-	InputValue string `orm:"column(input_value)" description:"值"`
-}
-
-func GetLzSurveyDataByTradeCode(condition string, pars []interface{}) (item []*lzSurveyData, err error) {
-	sql := ` SELECT  a.* FROM longzhong_survey_data AS a
-				INNER JOIN longzhong_survey_product AS b ON a.survey_product_id=b.survey_product_id
-				WHERE 1=1 `
-	o := orm.NewOrmUsingDB("edb")
-	if condition != "" {
-		sql += condition
-	}
-	sql += ` ORDER BY a.data_time DESC `
-	_, err = o.Raw(sql, pars).QueryRows(&item)
-	return
-}
-
-func GetEdbDataLzByCode(edbCode string) (items []*EdbInfoSearchData, err error) {
-	o := orm.NewOrmUsingDB("data")
-	sql := ` SELECT * FROM edb_data_lz WHERE edb_code=? ORDER BY data_time DESC LIMIT ? `
-	_, err = o.Raw(sql, edbCode, utils.EDB_DATA_LIMIT).QueryRows(&items)
-	return
-}
-
-func GetEdbDataByLz(edbCode, startDate, endDate string) (searchItem *EdbInfoSearch, err error) {
-	o := orm.NewOrmUsingDB("data")
-	to, err := o.Begin()
-	if err != nil {
-		return
-	}
-	defer func() {
-		if err != nil {
-			_ = to.Rollback()
-		} else {
-			_ = to.Commit()
-		}
-	}()
-	var condition string
-	var pars []interface{}
-
-	if edbCode != "" {
-		condition += " AND b.lz_code=? "
-		pars = append(pars, edbCode)
-	}
-
-	lzDataList, err := GetLzSurveyDataByTradeCode(condition, pars)
-	if err != nil {
-		return
-	}
-	searchItem = new(EdbInfoSearch)
-	searchItem.EdbCode = edbCode
-	dataLen := len(lzDataList)
-
-	if dataLen > 0 {
-		var isAdd bool
-		addSql := ` INSERT INTO edb_data_lz(edb_info_id,edb_code,data_time,value,create_time,modify_time,status,data_timestamp) values `
-		nowStr := time.Now().Format(utils.FormatDateTime)
-		dataList := make([]*EdbInfoSearchData, 0)
-		for i := 0; i < dataLen; i++ {
-			item := lzDataList[i]
-			eDate := item.DataTime
-			sValue := item.InputValue
-			dataTime, err := time.Parse(utils.FormatDate, eDate)
-			if err != nil {
-				return nil, err
-			}
-			timestamp := dataTime.UnixNano() / 1e6
-			timeStr := fmt.Sprintf("%d", timestamp)
-			addSql += "("
-			addSql += "0," + "'" + edbCode + "'" + "," + "'" + eDate + "'" + "," + sValue + "," + "'" + nowStr + "'" +
-				"," + "'" + nowStr + "'" + "," + "0" + "," + "'" + timeStr + "'"
-			addSql += "),"
-			isAdd = true
-		}
-		if isAdd {
-			addSql = strings.TrimRight(addSql, ",")
-			err = AddEdbDataLzBySql(addSql)
-			if err != nil {
-				utils.FileLogData.Info("AddEdbDataLzBySql Err:%s", err.Error())
-				return
-			}
-		}
-
-		dataList, err := GetEdbDataLzByCode(edbCode)
-		if err != nil {
-			utils.FileLogData.Info("GetEdbDataLzByCode Err:%s", err.Error())
-			return searchItem, err
-		}
-		minDate, maxDate, err := GetEdbDataLzMaxOrMinDate(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
-}
-
-func ModifyEdbDataLzStatus(edbInfoId int64, edbCode string) (err error) {
-	o := orm.NewOrmUsingDB("data")
-	sql := ` UPDATE edb_data_lz SET edb_info_id=?, status=1,modify_time=NOW() WHERE edb_code=? `
-	_, err = o.Raw(sql, edbInfoId, edbCode).Exec()
-	return
-}
-
-func GetEdbDataLzByCodeAndDate(edbCode string, startDate string) (count int, err error) {
-	o := orm.NewOrmUsingDB("data")
-	sql := ` SELECT COUNT(1) AS count FROM edb_data_lz WHERE edb_code=? AND data_time=? `
-	err = o.Raw(sql, edbCode, startDate).QueryRow(&count)
-	return
-}
-
-func ModifyEdbDataLz(edbInfoId int64, dataTime, value string) (err error) {
-	o := orm.NewOrmUsingDB("data")
-	sql := ` UPDATE edb_data_lz SET value=?,modify_time=NOW() WHERE edb_info_id=? AND data_time=? `
-	_, err = o.Raw(sql, value, edbInfoId, dataTime).Exec()
-	return
-}
-
-// 刷新隆众指标数据
-func RefreshEdbDataByLz(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
-	}
-	edbInfoIdStr := strconv.Itoa(edbInfoId)
-	//计算数据
-	var condition string
-	var pars []interface{}
-
-	if edbCode != "" {
-		condition += " AND b.lz_code=? "
-		pars = append(pars, edbCode)
-	}
-
-	if startDate != "" {
-		condition += " AND a.data_time>=? "
-		pars = append(pars, startDate)
-	}
-
-	if endDate != "" {
-		condition += " AND a.data_time<=? "
-		pars = append(pars, endDate)
-	}
-
-	lzDataList, err := GetLzSurveyDataByTradeCode(condition, pars)
-
-	addSql := ` INSERT INTO edb_data_lz(edb_info_id,edb_code,data_time,value,create_time,modify_time,status,data_timestamp) values `
-	var isAdd bool
-	for _, v := range lzDataList {
-		item := v
-		count, err := GetEdbDataLzByCodeAndDate(edbCode, v.DataTime)
-		if err != nil && err.Error() != utils.ErrNoRow() {
-			return err
-		}
-		if count <= 0 {
-			nowStr := time.Now().Format(utils.FormatDateTime)
-			eDate := item.DataTime
-			sValue := item.InputValue
-			dataTime, err := time.Parse(utils.FormatDate, eDate)
-			if err != nil {
-				return err
-			}
-			timestamp := dataTime.UnixNano() / 1e6
-			timeStr := fmt.Sprintf("%d", timestamp)
-			addSql += "("
-			addSql += edbInfoIdStr + "," + "'" + edbCode + "'" + "," + "'" + eDate + "'" + "," + sValue + "," + "'" + nowStr + "'" +
-				"," + "'" + nowStr + "'" + "," + "1" + "," + "'" + timeStr + "'"
-			addSql += "),"
-			isAdd = true
-		} else {
-			err = ModifyEdbDataLz(int64(edbInfoId), v.DataTime, v.InputValue)
-			if err != nil {
-				return err
-			}
-		}
-	}
-	if isAdd {
-		addSql = strings.TrimRight(addSql, ",")
-		_, err = to.Raw(addSql).Exec()
-		if err != nil {
-			return err
-		}
-	}
-	return
-}
-
-// 全部刷新隆众数据
-func RefreshAllEdbDataByLz(edbInfoId, source, subSource 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
-	}
-	edbInfoIdStr := strconv.Itoa(edbInfoId)
-	//计算数据
-	var condition string
-	var pars []interface{}
-
-	if edbCode != "" {
-		condition += " AND b.lz_code=? "
-		pars = append(pars, edbCode)
-	}
-
-	if startDate != "" {
-		condition += " AND a.data_time>=? "
-		pars = append(pars, startDate)
-	}
-
-	if endDate != "" {
-		condition += " AND a.data_time<=? "
-		pars = append(pars, endDate)
-	}
-
-	lzDataList, err := GetLzSurveyDataByTradeCode(condition, pars)
-
-	//获取指标所有数据
-	dataList := make([]*EdbDataBase, 0)
-	dataTableName := GetEdbDataTableName(source, subSource)
-	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_lz(edb_info_id,edb_code,data_time,value,create_time,modify_time,status,data_timestamp) values `
-	var isAdd bool
-	for _, v := range lzDataList {
-		item := v
-
-		eDate := item.DataTime
-		sValue := item.InputValue
-		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
-				}
-			}
-		}
-	}
-	if isAdd {
-		addSql = strings.TrimRight(addSql, ",")
-		_, err = to.Raw(addSql).Exec()
-		if err != nil {
-			return err
-		}
-	}
-	return
-}

+ 2 - 194
models/data_manage/edb_data_quarter.go

@@ -1,7 +1,6 @@
 package data_manage
 
 import (
-	"encoding/json"
 	"eta/eta_mobile/utils"
 	"fmt"
 	"github.com/beego/beego/v2/client/orm"
@@ -43,14 +42,14 @@ func AddCalculateQuarter(edbInfoId, source int, edbCode string) (err error) {
 	var pars []interface{}
 	condition += " AND edb_info_id=? "
 	pars = append(pars, edbInfoId)
-	dataList, err := GetEdbDataListAll(condition, pars, source, utils.DATA_SUB_SOURCE_EDB, 0)
+	dataList, err := GetAllEdbDataListData(edbInfoId, source, utils.DATA_SUB_SOURCE_EDB, "")
 	if err != nil {
 		return err
 	}
 
 	var yearArr []int
 	yearMap := make(map[int]int)
-	dataMap := make(map[string]*EdbInfoSearchData)
+	dataMap := make(map[string]*EdbData)
 	for _, v := range dataList {
 		//日其中获取年
 		itemDate, err := time.Parse(utils.FormatDate, v.DataTime)
@@ -203,197 +202,6 @@ func AddCalculateQuarter(edbInfoId, source int, edbCode string) (err error) {
 	return
 }
 
-// 指标季度数据计算(公历转农历)
-func AddCalculateQuarterV2(edbInfoId, source int, edbCode string) (err error) {
-	o := orm.NewOrmUsingDB("data")
-	to, err := o.Begin()
-	if err != nil {
-		return
-	}
-	defer func() {
-		if err != nil {
-			fmt.Println("Err:", err)
-			_ = to.Rollback()
-		} else {
-			_ = to.Commit()
-		}
-	}()
-
-	edbInfoIdStr := strconv.Itoa(edbInfoId)
-	fmt.Println(edbInfoIdStr)
-	//计算数据
-	var condition string
-	var pars []interface{}
-	condition += " AND edb_info_id=? "
-	pars = append(pars, edbInfoId)
-	dataList, err := GetEdbDataListAll(condition, pars, source, utils.DATA_SUB_SOURCE_EDB, 0)
-	if err != nil {
-		return err
-	}
-
-	var yearArr []int
-	yearMap := make(map[int]int)
-	dataMap := make(map[string]*EdbInfoSearchData)
-	for _, v := range dataList {
-		//日其中获取年
-		itemDate, err := time.Parse(utils.FormatDate, v.DataTime)
-		if err != nil {
-			return err
-		}
-		year := itemDate.Year()
-		if _, ok := yearMap[year]; !ok {
-			yearArr = append(yearArr, year)
-			yearMap[year] = year
-		}
-		dataMap[v.DataTime] = v
-	}
-	sort.Sort(sort.Reverse(sort.IntSlice(yearArr)))
-	addSql := ` INSERT INTO edb_data_quarter(edb_info_id,edb_code,data_time,value,create_time,modify_time,status,data_timestamp) values `
-	var isAdd bool
-	//yearLen := len(yearArr)
-
-	fmt.Println(yearArr)
-
-	for _, yv := range yearArr {
-		fmt.Println(yv)
-	}
-	fmt.Println("isAdd", isAdd)
-	if isAdd {
-		addSql = strings.TrimRight(addSql, ",")
-		utils.FileLog.Info(addSql)
-		_, err = to.Raw(addSql).Exec()
-		fmt.Println("err:", err)
-		if err != nil {
-			return err
-		}
-	}
-	return
-}
-
-// 指标季度数据计算(公历转农历)
-func AddCalculateQuarterV3(edbInfoId, source int, edbCode string, list []*EdbDataList) (err error) {
-	var errMsg string
-	defer func() {
-		if errMsg != "" {
-			fmt.Println("errMsg:", errMsg)
-		}
-	}()
-	lunarDate := "2017-01-01" //农历
-	fmt.Println(solarlunar.LunarToSolar(lunarDate, false))
-
-	dataList, err := GetHzTestEdbdata()
-	var yearArr []int
-	yearMap := make(map[int]int)
-	var cureentDate time.Time
-	for k, v := range dataList {
-		if k == 0 {
-			cureentDate = v.Dt
-		}
-		year := v.Dt.Year()
-		if _, ok := yearMap[year]; !ok {
-			yearArr = append(yearArr, year)
-		}
-		yearMap[year] = year
-	}
-	//排序
-	fmt.Println(yearArr)
-	thisYear := cureentDate.Year()
-	thisMonth := int(cureentDate.Month())
-
-	sort.Ints(yearArr)
-	fmt.Println("thisYear:", thisYear)
-
-	result := new(HzTestEdbdataResult)
-	for ky, vy := range yearArr {
-		if thisMonth < 11 {
-			currentYearCjnl := strconv.Itoa(thisYear) + "-01-01"               //当前年份春节农历
-			currentYearCjgl := solarlunar.LunarToSolar(currentYearCjnl, false) //当前年份春节公历
-			currentYearCjglDate, err := time.Parse(utils.FormatDate, currentYearCjgl)
-			if err != nil {
-				errMsg = "生成当前春节失败,Err:" + err.Error()
-				return err
-			}
-
-			fmt.Println(ky, vy)
-			preYear := vy
-			preYearCjnl := strconv.Itoa(preYear) + "-01-01"            //之前年份春节农历
-			preYearCjgl := solarlunar.LunarToSolar(preYearCjnl, false) //之前年份春节公历
-			preYearCjglDate, err := time.Parse(utils.FormatDate, preYearCjgl)
-			if err != nil {
-				errMsg = "生成历史年份春节失败,Err:" + err.Error()
-				return err
-			}
-			day := currentYearCjglDate.Sub(preYearCjglDate).Hours() / float64(24)
-			fmt.Println("day:", day)
-			items := new(HzTestEdbdataItems)
-			dataLen := len(dataList)
-			for i := dataLen - 1; i >= 0; i-- {
-				v := dataList[i]
-				newDate := v.Dt.AddDate(0, 0, int(day))
-				selectDateStr := strconv.Itoa(thisYear) + "-11" + "-30"
-				selectDate, _ := time.Parse(utils.FormatDate, selectDateStr)
-
-				if newDate.Before(selectDate) {
-					item := new(HzTestEdbdata)
-					item.TtradeCode = v.TtradeCode
-					item.Dt = newDate
-					item.Close = v.Close
-					timestamp := item.Dt.UnixNano() / 1e6
-					item.DataTimestamp = timestamp
-					items.Items = append(items.Items, item)
-				}
-			}
-			result.List = append(result.List, items)
-		} else {
-			fmt.Println(ky, vy)
-			nextYear := thisYear + 1
-			nextYearCjnl := strconv.Itoa(nextYear) + "-01-01"            //当前年份春节农历
-			nextYearCjgl := solarlunar.LunarToSolar(nextYearCjnl, false) //当前年份春节公历
-
-			nextYearCjglDate, err := time.Parse(utils.FormatDate, nextYearCjgl)
-			if err != nil {
-				errMsg = "生成当前春节失败,Err:" + err.Error()
-				return err
-			}
-
-			preYear := vy
-			preYearCjnl := strconv.Itoa(preYear) + "-01-01"            //之前年份春节农历
-			preYearCjgl := solarlunar.LunarToSolar(preYearCjnl, false) //之前年份春节公历
-			preYearCjglDate, err := time.Parse(utils.FormatDate, preYearCjgl)
-			if err != nil {
-				errMsg = "生成历史年份春节失败,Err:" + err.Error()
-				return err
-			}
-			day := nextYearCjglDate.Sub(preYearCjglDate).Hours() / float64(24)
-
-			fmt.Println("day:", day)
-			items := new(HzTestEdbdataItems)
-			dataLen := len(dataList)
-			for i := dataLen - 1; i >= 0; i-- {
-				v := dataList[i]
-				newDate := v.Dt.AddDate(0, 0, int(day))
-				selectDateStr := strconv.Itoa(nextYear) + "-05" + "-31"
-				selectDate, _ := time.Parse(utils.FormatDate, selectDateStr)
-
-				if newDate.Before(selectDate) {
-					item := new(HzTestEdbdata)
-					item.TtradeCode = v.TtradeCode
-					item.Dt = newDate
-					item.Close = v.Close
-					timestamp := item.Dt.UnixNano() / 1e6
-					item.DataTimestamp = timestamp
-					items.Items = append(items.Items, item)
-				}
-			}
-			result.List = append(result.List, items)
-		}
-
-	}
-	resultJson, err := json.Marshal(result)
-	utils.FileLog.Info(string(resultJson))
-	return
-}
-
 // 指标季度数据计算(公历转农历)
 func AddCalculateQuarterV4(dataList []*EdbDataList) (result *EdbDataResult, err error) {
 	var errMsg string

+ 0 - 87
models/data_manage/edb_data_sci.go

@@ -1,99 +1,12 @@
 package data_manage
 
 import (
-	"eta/eta_mobile/utils"
-	"fmt"
 	"github.com/beego/beego/v2/client/orm"
-	"strconv"
-	"strings"
-	"time"
 )
 
-type BaseFromSciDataSimple struct {
-	SciDataId          int `orm:"column(sci_data_id);pk"`
-	BaseFromSciIndexId int
-	IndexCode          string
-	DataTime           string
-	Value              string
-}
-
 func GetEdbDataSciMaxAndMinDate(edbCode string) (min_date, max_date string, err error) {
 	o := orm.NewOrmUsingDB("data")
 	sql := ` SELECT MIN(data_time) AS min_date,MAX(data_time) AS max_date FROM edb_data_sci WHERE edb_code=? `
 	err = o.Raw(sql, edbCode).QueryRow(&min_date, &max_date)
 	return
 }
-
-// 全部刷新有色数据
-func RefreshAllEdbDataBySci(edbInfoId, source, subSource 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
-	}
-	edbInfoIdStr := strconv.Itoa(edbInfoId)
-
-	//获取已存在指标所有数据
-	existDataList := make([]*EdbDataBase, 0)
-	dataTableName := GetEdbDataTableName(source, subSource)
-	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
-	}
-
-	sciDateList := make([]*BaseFromSciDataSimple, 0)
-	sciSql := ` SELECT * FROM base_from_sci_data WHERE index_code=? AND data_time>=? `
-	_, err = to.Raw(sciSql, edbCode, startDate).QueryRows(&sciDateList)
-	if err != nil {
-		return err
-	}
-
-	addSql := ` INSERT INTO edb_data_sci(edb_info_id,edb_code,data_time,value,create_time,modify_time,status,data_timestamp) values `
-	var isAdd bool
-	for _, sv := range sciDateList {
-		if existVal, ok := existDataMap[sv.DataTime]; !ok {
-			dataTime, err := time.Parse(utils.FormatDate, sv.DataTime)
-			if err != nil {
-				return err
-			}
-			timestamp := dataTime.UnixNano() / 1e6
-			timeStr := fmt.Sprintf("%d", timestamp)
-			addSql += GetAddSql(edbInfoIdStr, edbCode, sv.DataTime, timeStr, sv.Value)
-			isAdd = true
-		} else {
-			if existVal != sv.Value {
-				sql := ` UPDATE %s SET value=?,modify_time=NOW() WHERE edb_info_id=? AND data_time=? `
-				sql = fmt.Sprintf(sql, dataTableName)
-				_, err = to.Raw(sql, sv.Value, edbInfoId, sv.DataTime).Exec()
-				if err != nil {
-					return err
-				}
-			}
-		}
-	}
-	if isAdd {
-		addSql = strings.TrimRight(addSql, ",")
-		_, err = to.Raw(addSql).Exec()
-		if err != nil {
-			return err
-		}
-	}
-	return
-}

+ 0 - 63
models/data_manage/edb_data_ths_ds.go

@@ -1,63 +0,0 @@
-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
-}

+ 0 - 48
models/data_manage/edb_data_wind_wsd.go

@@ -13,51 +13,3 @@ func ModifyEdbInfoWindWsdDataStatus(source, subSource int, edbInfoId int64, edbC
 	_, 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
-}

+ 368 - 516
models/data_manage/edb_info.go

@@ -1,6 +1,9 @@
 package data_manage
 
 import (
+	"encoding/json"
+	"eta/eta_mobile/models/data_manage/line_equation/request"
+	"eta/eta_mobile/models/mgo"
 	"eta/eta_mobile/services/alarm_msg"
 	"eta/eta_mobile/utils"
 	"fmt"
@@ -8,6 +11,8 @@ import (
 	"strings"
 	"time"
 
+	"go.mongodb.org/mongo-driver/bson"
+
 	"github.com/beego/beego/v2/client/orm"
 	"github.com/rdlucklib/rdluck_tools/paging"
 )
@@ -225,26 +230,16 @@ func DeleteEdbInfoAndData(edbInfoId, source, subSource int) (err error) {
 		return
 	}
 
-	var tableName string
-	if subSource == 0 {
-		// 删除指标数据
-		tableName = GetEdbDataTableName(source, subSource)
+	// 删除指标的明细数据
+	if source == utils.DATA_SOURCE_BUSINESS && utils.UseMongo {
+		err = deleteAllEdbDataByMongo(to, edbInfoId, source, subSource)
 	} else {
-		if source == utils.DATA_SOURCE_WIND {
-			tableName = "edb_data_wind_wsd"
-		} else if source == utils.DATA_SOURCE_THS {
-			tableName = "edb_data_ths_ds"
-		}
+		err = deleteAllEdbDataByMysql(to, edbInfoId, source, subSource)
 	}
-
-	if tableName != "" {
-		sql = ` DELETE FROM %s WHERE edb_info_id=? `
-		sql = fmt.Sprintf(sql, tableName)
-		_, err = to.Raw(sql, edbInfoId).Exec()
-		if err != nil {
-			return
-		}
+	if err != nil {
+		return
 	}
+
 	//calculateTableName := GetEdbInfoCalculateTableName(source)
 	//if calculateTableName != "" {
 	//	sql = ` DELETE FROM %s WHERE edb_info_id=? `
@@ -264,6 +259,42 @@ func DeleteEdbInfoAndData(edbInfoId, source, subSource int) (err error) {
 	return
 }
 
+// deleteAllEdbDataByMysql
+// @Description: 删除指标的明细数据(mysql)
+// @author: Roc
+// @datetime 2024-05-09 13:31:54
+// @param to orm.TxOrmer
+// @param edbInfoId int
+// @param source int
+// @param subSource int
+// @return err error
+func deleteAllEdbDataByMysql(to orm.TxOrmer, edbInfoId, source, subSource int) (err error) {
+	tableName := GetEdbDataTableName(source, subSource)
+	if tableName == `` {
+		return
+	}
+
+	sql := fmt.Sprintf(` DELETE FROM %s WHERE edb_info_id=? `, tableName)
+	_, err = to.Raw(sql, edbInfoId).Exec()
+
+	return
+}
+
+// deleteAllEdbDataByMongo
+// @Description: 删除指标的明细数据(mongo)
+// @author: Roc
+// @datetime 2024-05-09 13:31:37
+// @param to orm.TxOrmer
+// @param edbInfoId int
+// @param source int
+// @param subSource int
+// @return err error
+func deleteAllEdbDataByMongo(to orm.TxOrmer, edbInfoId, source, subSource int) (err error) {
+	mogDataObj := mgo.EdbDataBusiness{}
+	err = mogDataObj.RemoveMany(bson.M{"edb_info_id": edbInfoId})
+	return
+}
+
 func GetEdbInfoCountByCondition(condition string, pars []interface{}) (count int, err error) {
 	o := orm.NewOrmUsingDB("data")
 	sql := ` SELECT COUNT(1) AS count FROM edb_info WHERE 1=1 `
@@ -538,7 +569,35 @@ type EdbInfoMaxAndMinInfo struct {
 	LatestValue float64 `description:"最新值"`
 }
 
+// GetEdbInfoMaxAndMinInfo
+// @Description: 获取指标最大最小值
+// @author: Roc
+// @datetime 2024-05-07 15:34:00
+// @param source int
+// @param subSource int
+// @param edbCode string
+// @return item *EdbInfoMaxAndMinInfo
+// @return err error
 func GetEdbInfoMaxAndMinInfo(source, subSource int, edbCode string) (item *EdbInfoMaxAndMinInfo, err error) {
+	// 自有数据需要额外处理(从mongo获取)
+	if source == utils.DATA_SOURCE_BUSINESS && utils.UseMongo {
+		return GetEdbInfoMaxAndMinInfoByMongo(source, subSource, edbCode)
+	}
+
+	// 默认走mysql
+	return GetEdbInfoMaxAndMinInfoByMysql(source, subSource, edbCode)
+}
+
+// GetEdbInfoMaxAndMinInfoByMysql
+// @Description: 从mysql中获取指标最大最小值
+// @author: Roc
+// @datetime 2024-05-07 15:33:43
+// @param source int
+// @param subSource int
+// @param edbCode string
+// @return item *EdbInfoMaxAndMinInfo
+// @return err error
+func GetEdbInfoMaxAndMinInfoByMysql(source, subSource int, edbCode string) (item *EdbInfoMaxAndMinInfo, err error) {
 	o := orm.NewOrmUsingDB("data")
 	sql := ``
 	tableName := GetEdbDataTableName(source, subSource)
@@ -557,88 +616,72 @@ func GetEdbInfoMaxAndMinInfo(source, subSource int, edbCode string) (item *EdbIn
 	return
 }
 
-func ModifyEdbInfoMaxAndMinInfo(edbInfoId int, item *EdbInfoMaxAndMinInfo) (err error) {
-	o := orm.NewOrmUsingDB("data")
-	sql := ` UPDATE edb_info SET start_date=?,end_date=?,min_value=?,max_value=?,is_update=2,latest_date=?,latest_value=?,modify_time=NOW() WHERE edb_info_id=? `
-	_, err = o.Raw(sql, item.MinDate, item.MaxDate, item.MinValue, item.MaxValue, item.MaxDate, item.LatestValue, edbInfoId).Exec()
-	return
-}
-
-func GetEdbInfoFilter(condition string, pars []interface{}) (list []*EdbInfoList, err error) {
-	o := orm.NewOrmUsingDB("data")
-	sql := ` SELECT * FROM edb_info WHERE 1=1  AND edb_info_type = 0 `
-	if condition != "" {
-		sql += condition
+// GetEdbInfoMaxAndMinInfoByMongo
+// @Description: 从mongo中获取指标最大最小值
+// @author: Roc
+// @datetime 2024-05-07 15:33:53
+// @param source int
+// @param subSource int
+// @param edbCode string
+// @return item *EdbInfoMaxAndMinInfo
+// @return err error
+func GetEdbInfoMaxAndMinInfoByMongo(source, subSource int, edbCode string) (item *EdbInfoMaxAndMinInfo, err error) {
+	mogDataObj := new(mgo.EdbDataBusiness)
+	pipeline := []bson.M{
+		{"$match": bson.M{"edb_code": edbCode}},
+		{"$group": bson.M{
+			"_id":       nil,
+			"min_date":  bson.M{"$min": "$data_time"},
+			"max_date":  bson.M{"$max": "$data_time"},
+			"min_value": bson.M{"$min": "$value"},
+			"max_value": bson.M{"$max": "$value"},
+		}},
+		{"$project": bson.M{"_id": 0}}, // 可选,如果不需要_id字段
+	}
+	result, err := mogDataObj.GetEdbInfoMaxAndMinInfo(pipeline)
+	if err != nil {
+		fmt.Println("EdbDataBusiness getEdbDataBusinessList Err:" + err.Error())
+		return
 	}
-	sql += ` ORDER BY create_time DESC `
-	_, err = o.Raw(sql, pars).QueryRows(&list)
-	return
-}
-
-//order:1升序,其余值为降序
-func GetEdbDataListAll(condition string, pars []interface{}, source, subSource, order int) (item []*EdbInfoSearchData, err error) {
-	o := orm.NewOrmUsingDB("data")
-	sql := ``
-	tableName := GetEdbDataTableName(source, subSource)
-	sql = ` SELECT * FROM %s WHERE 1=1 `
-	sql = fmt.Sprintf(sql, tableName)
 
-	if condition != "" {
-		sql += condition
+	if !result.MaxDate.IsZero() {
+		whereQuery := bson.M{"edb_code": edbCode, "data_time": result.MaxDate}
+		selectParam := bson.D{{"value", 1}, {"_id", 0}}
+		latestValue, tmpErr := mogDataObj.GetLatestValue(whereQuery, selectParam)
+		if tmpErr != nil {
+			err = tmpErr
+			return
+		}
+		result.LatestValue = latestValue.Value
+		result.EndValue = latestValue.Value
 	}
-	if order == 1 {
-		sql += ` ORDER BY data_time ASC `
-	} else {
-		sql += ` ORDER BY data_time DESC `
+
+	item = &EdbInfoMaxAndMinInfo{
+		MinDate:     result.MinDate.Format(utils.FormatDate),
+		MaxDate:     result.MaxDate.Format(utils.FormatDate),
+		MinValue:    result.MinValue,
+		MaxValue:    result.MaxValue,
+		LatestValue: result.LatestValue,
 	}
-	_, err = o.Raw(sql, pars).QueryRows(&item)
+
 	return
 }
 
-// GetLastEdbData 获取最近的一条指标数据
-func GetLastEdbData(condition string, pars []interface{}, source, subSource int) (item *EdbInfoSearchData, err error) {
+func ModifyEdbInfoMaxAndMinInfo(edbInfoId int, item *EdbInfoMaxAndMinInfo) (err error) {
 	o := orm.NewOrmUsingDB("data")
-	sql := ``
-	tableName := GetEdbDataTableName(source, subSource)
-	sql = ` SELECT * FROM %s WHERE 1=1 `
-	sql = fmt.Sprintf(sql, tableName)
-
-	if condition != "" {
-		sql += condition
-	}
-	sql += ` ORDER BY data_time DESC `
-	err = o.Raw(sql, pars).QueryRow(&item)
+	sql := ` UPDATE edb_info SET start_date=?,end_date=?,min_value=?,max_value=?,is_update=2,latest_date=?,latest_value=?,modify_time=NOW() WHERE edb_info_id=? `
+	_, err = o.Raw(sql, item.MinDate, item.MaxDate, item.MinValue, item.MaxValue, item.MaxDate, item.LatestValue, edbInfoId).Exec()
 	return
 }
 
-//order:1升序,其余值为降序
-func GetEdbDataCount(condition string, pars []interface{}, source, subSource int) (count int, err error) {
+func GetEdbInfoFilter(condition string, pars []interface{}) (list []*EdbInfoList, err error) {
 	o := orm.NewOrmUsingDB("data")
-	sql := ``
-	tableName := GetEdbDataTableName(source, subSource)
-	sql = ` SELECT COUNT(1) AS count FROM %s WHERE 1=1 `
-	sql = fmt.Sprintf(sql, tableName)
-
+	sql := ` SELECT * FROM edb_info WHERE 1=1  AND edb_info_type = 0 `
 	if condition != "" {
 		sql += condition
 	}
-	err = o.Raw(sql, pars).QueryRow(&count)
-	return
-}
-
-func ModifyCalculateEdbInfo(item *EditEdbInfoReq) (err error) {
-	o := orm.NewOrmUsingDB("data")
-	sql := ` UPDATE  edb_info
-			SET
-			  edb_name =?,
-			  edb_name_source =?,
-			  frequency = ?,
-			  unit = ?,
-			  classify_id = ?,
-			  calculate_formula=?,
-			  modify_time = NOW()
-			WHERE edb_info_id = ?`
-	_, err = o.Raw(sql, item.EdbName, item.EdbName, item.Frequency, item.Unit, item.ClassifyId, item.CalculateFormula, item.EdbInfoId).Exec()
+	sql += ` ORDER BY create_time DESC `
+	_, err = o.Raw(sql, pars).QueryRows(&list)
 	return
 }
 
@@ -649,69 +692,6 @@ type AddEdbInfoResp struct {
 	ExistEdbName []string `description:"重复指标名称"`
 }
 
-// 根据基础指标获取所有关联指标
-func GetNeedRefreshCalculateEdbInfoFromBase(fromEdbInfo int) (list []*EdbInfo, err error) {
-	o := orm.NewOrmUsingDB("data")
-	sql := ` SELECT b.*
-			FROM edb_info_calculate AS a
-			INNER JOIN edb_info AS b ON a.edb_info_id=b.edb_info_id
-			WHERE from_edb_info_id=? `
-	_, err = o.Raw(sql, fromEdbInfo).QueryRows(&list)
-	return
-}
-
-func GetEdbInfoCalculateCount(edbInfoId int) (count int, err error) {
-	o := orm.NewOrmUsingDB("data")
-	sql := ` SELECT COUNT(1) AS count FROM edb_info_calculate WHERE from_edb_info_id=? `
-	err = o.Raw(sql, edbInfoId).QueryRow(&count)
-	return
-}
-
-func GetEdbInfoCalculateLjzzyCount(edbInfoId int) (count int, err error) {
-	o := orm.NewOrmUsingDB("data")
-	sql := ` SELECT COUNT(1) AS count FROM edb_info_calculate_ljzzy WHERE from_edb_info_id=? `
-	err = o.Raw(sql, edbInfoId).QueryRow(&count)
-	return
-}
-
-func GetEdbInfoCalculateTbzCount(edbInfoId int) (count int, err error) {
-	o := orm.NewOrmUsingDB("data")
-	sql := ` SELECT COUNT(1) AS count FROM edb_info_calculate_tbz WHERE from_edb_info_id=? `
-	err = o.Raw(sql, edbInfoId).QueryRow(&count)
-	return
-}
-
-func GetEdbInfoCalculateTczCount(edbInfoId int) (count int, err error) {
-	o := orm.NewOrmUsingDB("data")
-	sql := ` SELECT COUNT(1) AS count FROM edb_info_calculate_tcz WHERE from_edb_info_id=? `
-	err = o.Raw(sql, edbInfoId).QueryRow(&count)
-	return
-}
-
-func GetEdbInfoCalculateNszydpjjsCount(edbInfoId int) (count int, err error) {
-	o := orm.NewOrmUsingDB("data")
-	sql := ` SELECT COUNT(1) AS count FROM edb_info_calculate_nszydpjjs WHERE from_edb_info_id=? `
-	err = o.Raw(sql, edbInfoId).QueryRow(&count)
-	return
-}
-
-func GetEdbInfoCalculateCountByCondition(source int, condition string, pars []interface{}) (count int, err error) {
-	o := orm.NewOrmUsingDB("data")
-	//calculateTableName := GetEdbInfoCalculateTableName(source)
-	//if calculateTableName == "" {
-	//	err = errors.New("无效的表名")
-	//	return
-	//}
-
-	sql := ` SELECT COUNT(1) AS count FROM edb_info_calculate_mapping WHERE 1=1 `
-	//sql = fmt.Sprintf(sql, calculateTableName)
-	if condition != "" {
-		sql += condition
-	}
-	err = o.Raw(sql, pars).QueryRow(&count)
-	return
-}
-
 // GetEdbInfoCalculateListByCondition 获取指标关系列表
 func GetEdbInfoCalculateListByCondition(condition string, pars []interface{}) (items []*EdbInfoCalculateMapping, err error) {
 	o := orm.NewOrmUsingDB("data")
@@ -730,36 +710,6 @@ func GetEdbInfoCalculateListByCondition(condition string, pars []interface{}) (i
 	return
 }
 
-func GetRefreshEdbInfoFromCalculate(edbInfoId, source int) (baseEdbInfoArr, calculateInfoArr []*EdbInfo, err error) {
-	calculateList, err := GetEdbInfoCalculateMap(edbInfoId, source)
-	if err != nil && err.Error() != utils.ErrNoRow() {
-		return
-	}
-	for _, item := range calculateList {
-		if item.EdbType == 1 {
-			baseEdbInfoArr = append(baseEdbInfoArr, item)
-		} else {
-			calculateInfoArr = append(calculateInfoArr, item)
-			newBaseEdbInfoArr, newCalculateInfoArr, _ := GetRefreshEdbInfoFromCalculate(item.EdbInfoId, item.Source)
-			baseEdbInfoArr = append(baseEdbInfoArr, newBaseEdbInfoArr...)
-			calculateInfoArr = append(calculateInfoArr, newCalculateInfoArr...)
-		}
-	}
-	return
-}
-
-// 获取基础指标对应的所有计算指标
-func GetEdbInfoAllCalculate(edbInfoId int) (list []*EdbInfo, err error) {
-	o := orm.NewOrmUsingDB("data")
-	sql := ` SELECT b.* FROM edb_info_calculate_mapping AS a
-			 INNER JOIN edb_info AS b ON a.edb_info_id=b.edb_info_id
-             WHERE a.from_edb_info_id=?
-			 GROUP BY a.edb_info_id
-			 ORDER BY a.edb_info_id ASC `
-	_, err = o.Raw(sql, edbInfoId).QueryRows(&list)
-	return
-}
-
 // GetEdbInfoAllCalculateByEdbInfoIdList 根据指标id集合 获取基础指标对应的所有计算指标
 func GetEdbInfoAllCalculateByEdbInfoIdList(edbInfoIdList []int) (list []*EdbInfo, err error) {
 	num := len(edbInfoIdList)
@@ -906,7 +856,122 @@ func ReplaceChartEdb(oldEdbInfo, newEdbInfo *EdbInfo) (relationEdbInfoIdList []i
 			return
 		}
 		replaceChartTotal = len(chartEdbMappingList)
+		// 查询所有的相关的图表信息
+		chartInfoIds := make([]string, 0)
+		if len(chartEdbMappingList) > 0 {
+			for _, chartEdbMapping := range chartEdbMappingList {
+				chartInfoIds = append(chartInfoIds, strconv.Itoa(chartEdbMapping.ChartInfoId))
+			}
+		}
 
+		if len(chartInfoIds) > 0 {
+			chartInfoList, e := GetChartInfoListByChartIdList(chartInfoIds)
+			if e != nil {
+				err = e
+				errmsg = "获取图表信息失败:Err:" + e.Error()
+				return
+			}
+			for _, chartInfo := range chartInfoList {
+				updateStr := make([]string, 0)
+				if chartInfo.EdbInfoIds != "" && strings.Contains(chartInfo.EdbInfoIds, strconv.Itoa(oldEdbInfo.EdbInfoId)) {
+					//需要更换
+					//解析字符串
+					edbInfoIds := strings.Split(chartInfo.EdbInfoIds, ",")
+					for i, edbInfoId := range edbInfoIds {
+						if edbInfoId == strconv.Itoa(oldEdbInfo.EdbInfoId) {
+							edbInfoIds[i] = strconv.Itoa(newEdbInfo.EdbInfoId)
+						}
+					}
+					chartInfo.EdbInfoIds = strings.Join(edbInfoIds, ",")
+					updateStr = append(updateStr, "EdbInfoIds")
+				}
+				if chartInfo.ExtraConfig != "" {
+					//判断是否是拟合方程或者散点图截面图
+					if chartInfo.Source == utils.CHART_SOURCE_LINE_EQUATION {
+						//解析配置内容
+						var lineChartInfoConfig request.LineChartInfoReq
+						err = json.Unmarshal([]byte(chartInfo.ExtraConfig), &lineChartInfoConfig)
+						if err != nil {
+							errmsg = "获取图表配置信息失败 json.Unmarshal:Err:" + err.Error()
+							return
+						}
+						xEdbInfoIdList := lineChartInfoConfig.XEdbInfoIdList
+						yEdbInfoIdList := lineChartInfoConfig.YEdbInfoIdList
+						if len(xEdbInfoIdList) > 0 {
+							// 循环判断是否存在
+							for k, xEdbInfoId := range xEdbInfoIdList {
+								if xEdbInfoId == oldEdbInfo.EdbInfoId {
+									xEdbInfoIdList[k] = newEdbInfo.EdbInfoId
+								}
+							}
+						}
+						if len(yEdbInfoIdList) > 0 {
+							// 循环判断是否存在
+							for k, yEdbInfoId := range yEdbInfoIdList {
+								if yEdbInfoId == oldEdbInfo.EdbInfoId {
+									yEdbInfoIdList[k] = newEdbInfo.EdbInfoId
+								}
+							}
+						}
+						// 替换新的指标信息
+						lineChartInfoConfig.XEdbInfoIdList = xEdbInfoIdList
+						lineChartInfoConfig.YEdbInfoIdList = yEdbInfoIdList
+						// 重新序列化
+						lineChartInfoConfigJson, e := json.Marshal(lineChartInfoConfig)
+						if e != nil {
+							err = e
+							errmsg = "图表配置信息序列化失败:json.Marshal Err: " + e.Error()
+							return
+						}
+						lineChartInfoConfigStr := string(lineChartInfoConfigJson)
+						// 更新图表配置信息
+						chartInfo.ExtraConfig = lineChartInfoConfigStr
+						updateStr = append(updateStr, "ExtraConfig")
+					} else if chartInfo.ChartType == utils.CHART_TYPE_SECTION_SCATTER {
+						//解析配置内容
+						var tmpExtraConfig SectionScatterReq
+						err = json.Unmarshal([]byte(chartInfo.ExtraConfig), &tmpExtraConfig)
+						if err != nil {
+							errmsg = "获取截面散点图配置信息失败 json.Unmarshal:Err:" + err.Error()
+							return
+						}
+						//找到指标信息,并替换
+						if len(tmpExtraConfig.SeriesList) > 0 {
+							for k1, series := range tmpExtraConfig.SeriesList {
+								for k2, item := range series.EdbInfoList {
+									if item.XEdbInfoId == oldEdbInfo.EdbInfoId {
+										tmpExtraConfig.SeriesList[k1].EdbInfoList[k2].XEdbInfoId = newEdbInfo.EdbInfoId
+									}
+									if item.YEdbInfoId == oldEdbInfo.EdbInfoId {
+										tmpExtraConfig.SeriesList[k1].EdbInfoList[k2].YEdbInfoId = newEdbInfo.EdbInfoId
+									}
+								}
+							}
+						}
+						// 重新序列化
+						sectionScatterConfigJson, e := json.Marshal(tmpExtraConfig)
+						if e != nil {
+							err = e
+							errmsg = "图表配置信息序列化失败:json.Marshal Err: " + e.Error()
+							return
+						}
+						sectionScatterConfigStr := string(sectionScatterConfigJson)
+						// 更新图表配置信息
+						chartInfo.ExtraConfig = sectionScatterConfigStr
+						updateStr = append(updateStr, "ExtraConfig")
+					}
+				}
+				if len(updateStr) > 0 {
+					updateStr = append(updateStr, "ModifyTime")
+					chartInfo.ModifyTime = time.Now()
+					err = chartInfo.Update(updateStr)
+					if err != nil {
+						errmsg = "更新图表信息失败:chartInfo.Update Err: " + err.Error()
+						return
+					}
+				}
+			}
+		}
 		if len(chartEdbMappingList) > 0 {
 			chartInfoIdList := make([]string, 0)
 			for _, mv := range chartEdbMappingList {
@@ -1011,341 +1076,6 @@ func ReplaceChartEdb(oldEdbInfo, newEdbInfo *EdbInfo) (relationEdbInfoIdList []i
 	return
 }
 
-// replaceRelationEdbInfo 替换关联指标
-func replaceRelationEdbInfo(mappingList []*EdbInfoCalculateMapping, oldEdbInfo, newEdbInfo *EdbInfo, sysAdminId int, sysAdminRealName string) (err error) {
-	errmsg := ``
-	defer func() {
-		if errmsg != "" {
-			fmt.Println("errmsg:" + errmsg)
-		}
-		if err != nil && errmsg != "" {
-			go alarm_msg.SendAlarmMsg("替换关联指标失败提醒,errmsg:"+errmsg, 3)
-			//go utils.SendEmail(utils.APPNAME+"【"+utils.RunMode+"】"+"替换指标失败提醒", "errmsg:"+errmsg, utils.EmailSendToUsers)
-		}
-	}()
-	//获取计算指标关联指标
-	allMappingList := make([]*EdbInfoCalculateMapping, 0)
-	allMapping := make(map[int]int)
-	tmpMapping := make(map[int]int)
-	for _, v := range mappingList {
-		if _, ok := allMapping[v.EdbInfoId]; !ok {
-			allMappingList = append(allMappingList, v)
-		}
-		newList, _ := GetAllCalculateV2(v.EdbInfoId, newEdbInfo.EdbInfoId, tmpMapping)
-		for _, nv := range newList {
-			if _, ok := allMapping[v.EdbInfoId]; !ok {
-				allMappingList = append(allMappingList, nv)
-			}
-			allMapping[v.EdbInfoId] = v.EdbInfoId
-		}
-		allMapping[v.EdbInfoId] = v.EdbInfoId
-	}
-	for mk, mv := range allMappingList { //原指标关联的所有计算指标
-		fmt.Println("mk/mv", mk, mv)
-		//重新计算计算指标
-		{
-			edbInfo, tmpErr := GetEdbInfoById(mv.EdbInfoId) //计算指标
-			err = tmpErr
-			if err != nil {
-				if err.Error() == utils.ErrNoRow() {
-					errmsg = "计算指标已被删除"
-				} else {
-					errmsg = "获取计算指标失败:err:" + err.Error()
-				}
-				return
-			}
-
-			fromEdbInfoList, tmpErr := GetEdbInfoCalculateDetail(mv.EdbInfoId, edbInfo.Source)
-			err = tmpErr
-			if err != nil {
-				errmsg = "获取计算指标失败:err:" + err.Error()
-				return
-			}
-			if len(fromEdbInfoList) <= 0 {
-				errmsg = "计算指标所依赖指标不存在"
-				err = fmt.Errorf("计算指标所依赖指标不存在")
-				return
-			}
-			fromEdbInfoItem := fromEdbInfoList[0]
-			if fromEdbInfoItem == nil {
-				return
-			}
-			fromEdbInfo, tmpErr := GetEdbInfoById(fromEdbInfoItem.FromEdbInfoId)
-			err = tmpErr
-			if err != nil {
-				errmsg = "获取计算指标 来源指标失败:err:" + err.Error()
-				return
-			}
-			edbCode := edbInfo.EdbCode
-			uniqueCode := edbInfo.UniqueCode
-			sourName := edbInfo.SourceName
-			source := edbInfo.Source
-			subSource := edbInfo.SubSource
-			edbInfoId := edbInfo.EdbInfoId
-
-			req := new(EdbInfoCalculateBatchSaveReq)
-			req.EdbInfoId = edbInfoId
-			req.EdbName = edbInfo.EdbName
-			req.Frequency = edbInfo.Frequency
-			req.Unit = edbInfo.Unit
-			req.ClassifyId = edbInfo.ClassifyId
-			req.FromEdbInfoId = fromEdbInfoList[0].FromEdbInfoId
-
-			if source == utils.DATA_SOURCE_CALCULATE {
-				//检验公式
-				var formulaStr string
-				var edbInfoIdBytes []string
-				for _, v := range fromEdbInfoList {
-					formulaStr += v.FromTag + ","
-					edbInfoIdBytes = append(edbInfoIdBytes, v.FromTag)
-				}
-				formulaStr = strings.Trim(formulaStr, ",")
-				formulaMap := CheckFormula(edbInfo.CalculateFormula)
-				for _, v := range formulaMap {
-					if !strings.Contains(formulaStr, v) {
-						errmsg = "公式错误,请重新填写"
-						err = fmt.Errorf("公式错误,请重新填写")
-						return
-					}
-				}
-
-				edbInfoList := make([]*EdbInfo, 0)
-
-				for _, v := range fromEdbInfoList {
-					edbInfo, tmpErr := GetEdbInfoById(v.FromEdbInfoId)
-					err = tmpErr
-					if err != nil {
-						if err.Error() == utils.ErrNoRow() {
-							errmsg = "指标 " + strconv.Itoa(v.FromEdbInfoId) + " 不存在"
-						} else {
-							errmsg = "获取指标失败:Err:" + err.Error()
-						}
-						return
-					}
-					edbInfoList = append(edbInfoList, edbInfo)
-				}
-				//清除历史数据
-				err = DeleteCalculateData(edbInfoId)
-				if err != nil {
-					errmsg = "清空运算指标失败:Err:" + err.Error() + " edb_info_id:" + strconv.Itoa(edbInfoId)
-					return
-				}
-				err = Calculate(edbInfoList, int(edbInfoId), edbCode, edbInfo.CalculateFormula, edbInfoIdBytes)
-				if err != nil {
-					errmsg = "生成计算指标失败,Calculate Err:" + err.Error()
-					return
-				}
-			} else if source == utils.DATA_SOURCE_CALCULATE_LJZZY {
-				_, err = AddCalculateLjzzy(req, fromEdbInfo, edbCode, uniqueCode, sysAdminId, sysAdminRealName)
-			} else if source == utils.DATA_SOURCE_CALCULATE_TBZ {
-				sourName = "同比值"
-				edbInfoId, err = AddCalculateTbz(req, fromEdbInfo, edbCode, uniqueCode, sysAdminId, sysAdminRealName)
-			} else if source == utils.DATA_SOURCE_CALCULATE_TCZ {
-				sourName = "同差值"
-				edbInfoId, err = AddCalculateTcz(req, fromEdbInfo, edbCode, uniqueCode, sysAdminId, sysAdminRealName)
-			} else if source == utils.DATA_SOURCE_CALCULATE_NSZYDPJJS {
-				sourName = "N数值移动平均计算"
-				formulaInt, _ := strconv.Atoi(edbInfo.CalculateFormula)
-				edbInfoId, err = AddCalculateNszydpjjs(req, fromEdbInfo, edbCode, uniqueCode, sysAdminId, sysAdminRealName, formulaInt)
-			} else if source == utils.DATA_SOURCE_CALCULATE_HBZ {
-				sourName = "环比值"
-				formulaInt, _ := strconv.Atoi(edbInfo.CalculateFormula)
-				edbInfoId, err = AddCalculateHbz(req, fromEdbInfo, edbCode, uniqueCode, sysAdminId, sysAdminRealName, formulaInt)
-			} else if source == utils.DATA_SOURCE_CALCULATE_HCZ {
-				sourName = "环差值"
-				formulaInt, _ := strconv.Atoi(edbInfo.CalculateFormula)
-				edbInfoId, err = AddCalculateHcz(req, fromEdbInfo, edbCode, uniqueCode, sysAdminId, sysAdminRealName, formulaInt)
-			} else if source == utils.DATA_SOURCE_CALCULATE_BP {
-				sourName = "变频"
-				fmt.Println("变频", req, fromEdbInfo, edbCode, uniqueCode, sysAdminId, sysAdminRealName)
-				edbInfoId, err = AddCalculateBp(req, fromEdbInfo, edbCode, uniqueCode, sysAdminId, sysAdminRealName)
-			} else if source == utils.DATA_SOURCE_CALCULATE_TIME_SHIFT {
-				req2 := &EdbInfoCalculateBatchEditReq{
-					EdbName:       edbInfo.EdbName,
-					Frequency:     edbInfo.Frequency,
-					Unit:          edbInfo.Unit,
-					ClassifyId:    edbInfo.ClassifyId,
-					Formula:       edbInfo.CalculateFormula,
-					EdbInfoId:     edbInfo.EdbInfoId,
-					FromEdbInfoId: fromEdbInfoList[0].FromEdbInfoId,
-					Source:        edbInfo.Source,
-					MoveType:      edbInfo.MoveType,
-					MoveFrequency: edbInfo.MoveFrequency,
-				}
-				sourName = "时间移位"
-				edbInfoId, err = EditCalculateTimeShift(req2, fromEdbInfo, edbCode, edbInfo)
-			} else if source == utils.DATA_SOURCE_CALCULATE_ZJPJ {
-				edbInfoIdArr := make([]EdbInfoFromTag, 0)
-				//A指标
-				aFromEdbInfoId := fromEdbInfoList[0].FromEdbInfoId
-				for _, v := range fromEdbInfoList {
-					if v.FromTag == "A" {
-						if v.FromEdbInfoId == oldEdbInfo.EdbInfoId {
-							aFromEdbInfoId = newEdbInfo.EdbInfoId
-						} else {
-							aFromEdbInfoId = fromEdbInfoList[0].FromEdbInfoId
-						}
-					}
-					if v.FromTag == "B" {
-						if v.FromEdbInfoId == oldEdbInfo.EdbInfoId {
-							edbInfoIdArr = append(edbInfoIdArr, EdbInfoFromTag{
-								EdbInfoId: newEdbInfo.EdbInfoId,
-								FromTag:   v.FromTag,
-								MoveValue: v.MoveValue,
-							})
-						} else {
-							edbInfoIdArr = append(edbInfoIdArr, EdbInfoFromTag{
-								EdbInfoId: v.FromEdbInfoId,
-								FromTag:   v.FromTag,
-								MoveValue: v.MoveValue,
-							})
-						}
-					}
-				}
-				req2 := &EdbInfoCalculateBatchEditReq{
-					EdbName:       edbInfo.EdbName,
-					Frequency:     edbInfo.Frequency,
-					Unit:          edbInfo.Unit,
-					ClassifyId:    edbInfo.ClassifyId,
-					Formula:       edbInfo.CalculateFormula,
-					EdbInfoId:     edbInfo.EdbInfoId,
-					FromEdbInfoId: aFromEdbInfoId,
-					Source:        edbInfo.Source,
-					MoveType:      edbInfo.MoveType,
-					MoveFrequency: edbInfo.MoveFrequency,
-					EdbInfoIdArr:  edbInfoIdArr,
-				}
-
-				sourName = "直接拼接"
-				if len(req2.EdbInfoIdArr) != 1 {
-					errmsg = "请传入拼接日期之后的指标"
-					err = fmt.Errorf("请传入拼接日期之后的指标")
-					return
-				}
-
-				secondEdbInfoReq := req2.EdbInfoIdArr[0]
-				secondEdbInfo, tmpErr := GetEdbInfoById(secondEdbInfoReq.EdbInfoId)
-				err = tmpErr
-				if err != nil {
-					errmsg = "获取拼接日期之后的指标信息失败:Err:" + err.Error()
-					err = fmt.Errorf("获取拼接日期之后的指标信息失败:Err:" + err.Error())
-					return
-				}
-
-				if fromEdbInfo.EdbInfoId == secondEdbInfo.EdbInfoId {
-					errmsg = "两个指标不允许为同一个"
-					err = fmt.Errorf("两个指标不允许为同一个")
-					return
-				}
-				tmpEdbInfoId, tmpErr := EditCalculateZjpj(req2, edbInfo, fromEdbInfo, secondEdbInfo)
-				err = tmpErr
-				edbInfoId = tmpEdbInfoId
-			} else if source == utils.DATA_SOURCE_CALCULATE_LJZTBPJ { //累计值同比拼接
-				edbInfoIdArr := make([]EdbInfoFromTag, 0)
-				//A指标
-				aFromEdbInfoId := fromEdbInfoList[0].FromEdbInfoId
-				for _, v := range fromEdbInfoList {
-					if v.FromTag == "A" {
-						if v.FromEdbInfoId == oldEdbInfo.EdbInfoId {
-							aFromEdbInfoId = newEdbInfo.EdbInfoId
-						} else {
-							aFromEdbInfoId = fromEdbInfoList[0].FromEdbInfoId
-						}
-					}
-					if v.FromTag == "B" {
-						if v.FromEdbInfoId == oldEdbInfo.EdbInfoId {
-							edbInfoIdArr = append(edbInfoIdArr, EdbInfoFromTag{
-								EdbInfoId: newEdbInfo.EdbInfoId,
-								FromTag:   v.FromTag,
-								MoveValue: v.MoveValue,
-							})
-						} else {
-							edbInfoIdArr = append(edbInfoIdArr, EdbInfoFromTag{
-								EdbInfoId: v.FromEdbInfoId,
-								FromTag:   v.FromTag,
-								MoveValue: v.MoveValue,
-							})
-						}
-					}
-				}
-
-				req2 := &EdbInfoCalculateBatchEditReq{
-					EdbName:       edbInfo.EdbName,
-					Frequency:     edbInfo.Frequency,
-					Unit:          edbInfo.Unit,
-					ClassifyId:    edbInfo.ClassifyId,
-					Formula:       edbInfo.CalculateFormula,
-					EdbInfoId:     edbInfo.EdbInfoId,
-					FromEdbInfoId: aFromEdbInfoId,
-					Source:        edbInfo.Source,
-					MoveType:      edbInfo.MoveType,
-					MoveFrequency: edbInfo.MoveFrequency,
-					EdbInfoIdArr:  edbInfoIdArr,
-				}
-
-				sourName = "累计值同比拼接"
-
-				if fromEdbInfo.Frequency != "月度" {
-					errmsg = "累计值同比拼接,待拼接指标只能筛选月度指标"
-					err = fmt.Errorf("累计值同比拼接,待拼接指标只能筛选月度指标")
-					return
-				}
-				if len(req2.EdbInfoIdArr) != 1 {
-					errmsg = "请传入同比值指标"
-					err = fmt.Errorf("请传入同比值指标")
-					return
-				}
-
-				secondEdbInfoReq := req2.EdbInfoIdArr[0]
-				tbzEdbInfo, tmpErr := GetEdbInfoById(secondEdbInfoReq.EdbInfoId)
-				err = tmpErr
-				if err != nil {
-					errmsg = "获取同比值指标信息失败:Err:" + err.Error()
-					err = fmt.Errorf("获取同比值指标信息失败:Err:" + err.Error())
-					return
-				}
-				if tbzEdbInfo.Source != utils.DATA_SOURCE_CALCULATE_TBZ {
-					errmsg = "指标必须是传入同比值指标类型"
-					err = fmt.Errorf("指标必须是传入同比值指标类型")
-					return
-				}
-				if tbzEdbInfo.Frequency != "月度" {
-					errmsg = "同比值指标只能筛选月度指标"
-					err = fmt.Errorf("同比值指标只能筛选月度指标")
-					return
-				}
-
-				if fromEdbInfo.EdbInfoId == tbzEdbInfo.EdbInfoId {
-					errmsg = "两个指标不允许为同一个"
-					err = fmt.Errorf("两个指标不允许为同一个")
-					return
-				}
-				tmpEdbInfoId, tmpErr := EditCalculateLjztbpj(req2, edbInfo, fromEdbInfo, tbzEdbInfo)
-				err = tmpErr
-				edbInfoId = tmpEdbInfoId
-			} else if source == utils.DATA_SOURCE_PYTHON {
-				//python代码运算的过滤
-				continue
-			} else {
-				errmsg = "无效计算方式,source:" + strconv.Itoa(source)
-				err = fmt.Errorf("无效计算方式,source:" + strconv.Itoa(source))
-				return
-			}
-			maxAndMinItem, tmpErr := GetEdbInfoMaxAndMinInfo(source, subSource, edbCode)
-			err = tmpErr
-			if err != nil && err.Error() != utils.ErrNoRow() {
-				errmsg = "生成" + sourName + "失败,GetEdbInfoMaxAndMinInfo Err:" + err.Error()
-				err = fmt.Errorf("生成" + sourName + "失败,GetEdbInfoMaxAndMinInfo Err:" + err.Error())
-				return
-			}
-			if maxAndMinItem != nil {
-				err = ModifyEdbInfoMaxAndMinInfo(edbInfoId, maxAndMinItem)
-			}
-		}
-	}
-	return
-}
-
 type EdbInfoView struct {
 	EdbInfoId        int    `orm:"column(edb_info_id);pk"`
 	EdbInfoType      int    `description:"指标类型,0:普通指标,1:预测指标"`
@@ -1695,7 +1425,7 @@ type SetEdbDataInsertConfigReq struct {
 // GetEdbInfoByClassifyId 用于分类展示
 func GetEdbInfoByClassifyId(classifyId, edbInfoType, adminId int) (items []*EdbClassifyItems, err error) {
 	o := orm.NewOrmUsingDB("data")
-	sql := ` SELECT edb_info_id,classify_id,edb_name_source AS classify_name,edb_name_en AS classify_name_en,unique_code,source_name,source,sys_user_id,sys_user_real_name,start_date,edb_code,edb_type, sort,is_join_permission FROM edb_info WHERE classify_id = ? AND edb_info_type = ?`
+	sql := ` SELECT edb_info_id,classify_id,edb_name AS classify_name,edb_name_en AS classify_name_en,unique_code,source_name,source,sys_user_id,sys_user_real_name,start_date,edb_code,edb_type, sort,is_join_permission FROM edb_info WHERE classify_id = ? AND edb_info_type = ?`
 
 	pars := []interface{}{classifyId, edbInfoType}
 	// 如果筛选了用户id
@@ -1713,6 +1443,7 @@ type EdbAndClassify struct {
 	EdbCode            string `description:"指标code"`
 	UniqueCode         string `description:"唯一code"`
 	EdbName            string `description:"指标名称"`
+	ClassifyId         int    `description:"所属分类id"`
 	FirstClassifyId    int    `description:"第1级的分类id"`
 	FirstClassifyName  string `description:"第1级的分类名称"`
 	SecondClassifyId   int    `description:"第2级的分类id"`
@@ -1726,9 +1457,7 @@ func GetEdbInfoAndClassifyListByEdbIdList(edbIdList []int) (items []*EdbAndClass
 		return
 	}
 	o := orm.NewOrmUsingDB("data")
-	sql := ` SELECT a.edb_info_id,a.edb_code,a.unique_code,a.edb_name,b.classify_id as second_classify_id,b.classify_name as second_classify_name,c.classify_id as first_classify_id,c.classify_name as first_classify_name FROM edb_info AS a
-			JOIN edb_classify b on a.classify_id=b.classify_id
-			JOIN edb_classify c on b.parent_id=c.classify_id
+	sql := ` SELECT a.edb_info_id,a.edb_code,a.unique_code,a.edb_name,a.classify_id FROM edb_info AS a
 			WHERE a.edb_info_id in (` + utils.GetOrmInReplace(num) + `) `
 
 	_, err = o.Raw(sql, edbIdList).QueryRows(&items)
@@ -1943,3 +1672,126 @@ func ModifyEdbInfoBaseTimeById(edbInfoId int, cTime time.Time) (err error) {
 	_, err = o.Raw(sql, cTime, edbInfoId).Exec()
 	return
 }
+
+// GetEdbInfoByNameArr 根据名称获取指标
+func GetEdbInfoByNameArr(names []string, edbInfoType int) (items []*EdbInfo, err error) {
+	if len(names) == 0 {
+		return
+	}
+	o := orm.NewOrmUsingDB("data")
+	sql := fmt.Sprintf(`SELECT edb_info_id, edb_code, edb_name FROM edb_info WHERE edb_name IN (%s) AND edb_info_type = ? `, utils.GetOrmInReplace(len(names)))
+	_, err = o.Raw(sql, names, edbInfoType).QueryRows(&items)
+	return
+}
+
+// GetEdbCodesBySource 根据来源获取指标编码
+func GetEdbCodesBySource(source int) (items []*EdbInfo, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT edb_info_id, edb_code, unique_code, classify_id FROM edb_info WHERE source = ? `
+	_, err = o.Raw(sql, source).QueryRows(&items)
+	return
+}
+
+// GetAllEdbDataListData
+// @Description: 获取指标的所有数据
+// @author: Roc
+// @datetime 2024-05-07 15:18:27
+// @param edbInfoId int
+// @param source int
+// @param subSource int
+// @param startDataTime string
+// @return dataList []*EdbData
+// @return err error
+func GetAllEdbDataListData(edbInfoId, source, subSource int, startDataTime string) (dataList []*EdbData, err error) {
+	// 自有数据需要额外处理(从mongo获取)
+	if source == utils.DATA_SOURCE_BUSINESS && utils.UseMongo {
+		return getAllDataByMongo(edbInfoId, source, subSource, startDataTime)
+	}
+
+	// 默认走mysql
+	return getAllDataByMysql(edbInfoId, source, subSource, startDataTime)
+}
+
+// getAllDataByMysql
+// @Description: 从mysql获取指标的所有数据
+// @author: Roc
+// @datetime 2024-05-07 15:18:41
+// @param edbInfoId int
+// @param source int
+// @param subSource int
+// @param startDataTime string
+// @return dataList []*data_manage.EdbData
+// @return err error
+func getAllDataByMysql(edbInfoId, source, subSource int, startDataTime string) (dataList []*EdbData, err error) {
+	dataList = make([]*EdbData, 0)
+	var dataCondition string
+	var dataPars []interface{}
+
+	dataCondition += ` AND edb_info_id=? `
+	dataPars = append(dataPars, edbInfoId)
+
+	// 结束日期
+	if startDataTime != "" {
+		dataCondition += ` AND data_time > ? `
+		dataPars = append(dataPars, startDataTime)
+	}
+
+	// 获取列表数据
+	dataList, err = GetAllEdbDataListByCondition(dataCondition, dataPars, source, subSource)
+	if err != nil {
+		return
+	}
+
+	return
+}
+
+// getAllDataByMongo
+// @Description: 从mongo获取指标的所有数据
+// @author: Roc
+// @datetime 2024-05-07 15:18:53
+// @param edbInfoId int
+// @param source int
+// @param subSource int
+// @param startDataTime string
+// @return dataList []*data_manage.EdbData
+// @return err error
+func getAllDataByMongo(edbInfoId, source, subSource int, startDataTime string) (dataList []*EdbData, err error) {
+	dataList = make([]*EdbData, 0)
+
+	mogDataObj := mgo.EdbDataBusiness{}
+	// 构建查询条件
+	queryConditions := bson.M{
+		"edb_info_id": edbInfoId,
+	}
+
+	// 数据日期
+	dateCondition, err := mgo.BuildDateCondition(startDataTime, "")
+	if err != nil {
+		return
+	}
+	if len(dateCondition) > 0 {
+		queryConditions["data_time"] = dateCondition
+	}
+
+	// 获取列表数据
+	tmpDataList, tmpErr := mogDataObj.GetAllDataList(queryConditions, []string{"-data_time"})
+	if tmpErr != nil {
+		err = tmpErr
+		return
+	}
+	for k, v := range tmpDataList {
+		dataList = append(dataList, &EdbData{
+			EdbDataId: k + 1,
+			EdbInfoId: v.EdbInfoId,
+			DataTime:  v.DataTime.Format(utils.FormatDate),
+			Value:     v.Value,
+		})
+	}
+
+	return
+}
+
+type ReplaceEdbInfoItem struct {
+	OldEdbInfo *EdbInfo
+	NewEdbInfo *EdbInfo
+}

+ 3 - 91
models/data_manage/edb_info_calculate.go

@@ -1,16 +1,13 @@
 package data_manage
 
 import (
-	"errors"
-	"eta/eta_mobile/utils"
 	"fmt"
 	"strconv"
-	"strings"
-	"time"
 
 	"github.com/beego/beego/v2/client/orm"
 	"github.com/rdlucklib/rdluck_tools/paging"
-	"github.com/yidane/formula"
+	"strings"
+	"time"
 )
 
 type EdbInfoCalculateSaveReq struct {
@@ -67,6 +64,7 @@ type EdbInfoCalculateDetail struct {
 	FromEdbInfoId      int       `description:"计算指标id"`
 	FromEdbCode        string    `description:"计算指标编码"`
 	FromEdbName        string    `description:"计算指标名称"`
+	FromEdbNameEn      string    `description:"计算指标名称"`
 	FromSource         int       `description:"计算指标来源"`
 	FromSourceName     string    `description:"计算指标来源名称"`
 	FromTag            string    `description:"来源指标标签"`
@@ -441,92 +439,6 @@ func GetFormulaMap() map[string]string {
 	return funMap
 }
 
-func Calculate(edbInfoIdArr []*EdbInfo, edbInfoId int, edbCode, formulaStr string, edbInfoIdBytes []string) (err error) {
-	defer func() {
-		if err != nil {
-			utils.FileLog.Info("Calculate Err:%s" + err.Error())
-		}
-	}()
-	saveDataMap := make(map[string]map[int]float64)
-	for _, v := range edbInfoIdArr {
-		var condition string
-		var pars []interface{}
-		condition += " AND edb_info_id=? "
-		pars = append(pars, v.EdbInfoId)
-		dataList, err := GetEdbDataListAll(condition, pars, v.Source, v.SubSource, 1)
-		if err != nil {
-			return 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 formulaStr == "" {
-			return
-		}
-		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
-			}
-		} else {
-			fmt.Println("formulaFormStr is empty")
-		}
-	}
-	if isAdd {
-		addSql = strings.TrimRight(addSql, ",")
-		AddEdbDataCalculateBySql(addSql)
-		if err != nil {
-			fmt.Println("AddEdbDataCalculate Err:" + err.Error())
-			return err
-		}
-	}
-	return
-}
-
 // SaveAdjustEdbInfoReq 保存数据调整请求参数(请求指标服务)
 type SaveAdjustEdbInfoReq struct {
 	AdminId       int                    `description:"添加人id"`

+ 0 - 157
models/data_manage/edb_info_calculate_bp.go

@@ -1,157 +0,0 @@
-package data_manage
-
-import (
-	"eta/eta_mobile/utils"
-	"fmt"
-	"github.com/beego/beego/v2/client/orm"
-	"github.com/shopspring/decimal"
-	"strconv"
-	"strings"
-	"time"
-)
-
-// 变频
-func AddCalculateBp(req *EdbInfoCalculateBatchSaveReq, fromEdbInfo *EdbInfo, edbCode, uniqueCode string, sysUserId int, sysUserRealName string) (edbInfoId int, err error) {
-	fmt.Println("AddCalculateBp")
-	o := orm.NewOrmUsingDB("data")
-	to, err := o.Begin()
-	if err != nil {
-		return
-	}
-	defer func() {
-		if err != nil {
-			fmt.Println("AddCalculateBp,Err:" + err.Error())
-			_ = to.Rollback()
-		} else {
-			_ = to.Commit()
-		}
-	}()
-	if req.EdbInfoId <= 0 {
-		edbInfo := new(EdbInfo)
-		edbInfo.Source = utils.DATA_SOURCE_CALCULATE_BP
-		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.Formula
-		edbInfo.EdbType = 2
-		newEdbInfoId, tmpErr := to.Insert(edbInfo)
-		if tmpErr != nil {
-			return edbInfoId, tmpErr
-		}
-		edbInfoId = int(newEdbInfoId)
-		//关联关系
-		{
-			calculateMappingItem := new(EdbInfoCalculateMapping)
-			calculateMappingItem.CreateTime = time.Now()
-			calculateMappingItem.ModifyTime = time.Now()
-			calculateMappingItem.Sort = 1
-			calculateMappingItem.EdbCode = edbCode
-			calculateMappingItem.EdbInfoId = edbInfoId
-			calculateMappingItem.FromEdbInfoId = fromEdbInfo.EdbInfoId
-			calculateMappingItem.FromEdbCode = fromEdbInfo.EdbCode
-			calculateMappingItem.FromEdbName = fromEdbInfo.EdbName
-			calculateMappingItem.FromSource = fromEdbInfo.Source
-			calculateMappingItem.FromSourceName = fromEdbInfo.SourceName
-			calculateMappingItem.FromTag = ""
-			calculateMappingItem.Source = edbInfo.Source
-			calculateMappingItem.SourceName = edbInfo.SourceName
-			_, err = to.Insert(calculateMappingItem)
-			if err != nil {
-				return
-			}
-		}
-	} else {
-		edbInfoId = req.EdbInfoId
-		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)
-		_, err = to.Raw(deleteSql, req.EdbInfoId).Exec()
-		if err != nil {
-			return 0, err
-		}
-	}
-
-	edbInfoIdStr := strconv.Itoa(edbInfoId)
-	fmt.Println("edbInfoIdStr:" + edbInfoIdStr)
-	//计算数据
-	var condition string
-	var pars []interface{}
-	condition += " AND edb_info_id=? "
-	if req.EdbInfoId <= 0 {
-		pars = append(pars, req.FromEdbInfoId)
-	} else {
-		pars = append(pars, fromEdbInfo.EdbInfoId)
-	}
-	dataList, err := GetEdbDataListAll(condition, pars, fromEdbInfo.Source, fromEdbInfo.SubSource, 0)
-	if err != nil {
-		return edbInfoId, err
-	}
-
-	addSql := ` INSERT INTO edb_data_calculate_bp(edb_info_id,edb_code,data_time,value,create_time,modify_time,status,data_timestamp) values `
-	var isAdd bool
-	existMap := make(map[string]string)
-	dataLen := len(dataList)
-	fmt.Println("dataLen:", dataLen)
-
-	for i := 0; i < dataLen; i++ {
-		//当期
-		currentItem := dataList[i]
-		currentDate, _ := time.Parse(utils.FormatDate, currentItem.DataTime)
-		var day int
-		var preItem *EdbInfoSearchData
-		var preDate time.Time
-		if i == 0 {
-			day = int(time.Now().Sub(currentDate).Hours() / float64(24))
-			preDate = time.Now()
-		} else {
-			j := i - 1
-			if j < dataLen {
-				preItem = dataList[j]
-				preDate, _ = time.Parse(utils.FormatDate, preItem.DataTime)
-				day = int(preDate.Sub(currentDate).Hours() / float64(24))
-				utils.FileLog.Info("preItem.DataTime:" + preItem.DataTime + ";currentItem.DataTime" + currentItem.DataTime)
-			}
-		}
-		for k := 0; k <= day; k++ {
-			needDay := preDate.AddDate(0, 0, -k)
-			needDayStr := needDay.Format(utils.FormatDate)
-			existKey := edbCode + needDayStr
-			if _, ok := existMap[existKey]; !ok {
-				timestamp := needDay.UnixNano() / 1e6
-				timestampStr := fmt.Sprintf("%d", timestamp)
-				valStr := decimal.NewFromFloat(currentItem.Value).String()
-				addSql += GetAddSql(edbInfoIdStr, edbCode, needDayStr, timestampStr, valStr)
-				isAdd = true
-			}
-			existMap[existKey] = needDayStr
-		}
-		existKey := edbCode + currentItem.DataTime
-		if _, ok := existMap[existKey]; !ok {
-			currentDate, _ := time.Parse(utils.FormatDate, currentItem.DataTime)
-			timestamp := currentDate.UnixNano() / 1e6
-			timestampStr := fmt.Sprintf("%d", timestamp)
-			valStr := decimal.NewFromFloat(currentItem.Value).String()
-			addSql += GetAddSql(edbInfoIdStr, edbCode, currentItem.DataTime, timestampStr, valStr)
-			isAdd = true
-		}
-		existMap[existKey] = currentItem.DataTime
-	}
-	if isAdd {
-		addSql = strings.TrimRight(addSql, ",")
-		_, err = to.Raw(addSql).Exec()
-		if err != nil {
-			return edbInfoId, err
-		}
-	}
-	return
-}

+ 0 - 144
models/data_manage/edb_info_calculate_hbz.go

@@ -1,144 +0,0 @@
-package data_manage
-
-import (
-	"eta/eta_mobile/utils"
-	"fmt"
-	"github.com/beego/beego/v2/client/orm"
-	"strconv"
-	"strings"
-	"time"
-
-	"github.com/shopspring/decimal"
-)
-
-// 环比值
-func AddCalculateHbz(req *EdbInfoCalculateBatchSaveReq, fromEdbInfo *EdbInfo, edbCode, uniqueCode string, sysUserId int, sysUserRealName string, formulaInt int) (edbInfoId int, err error) {
-	fmt.Println("AddCalculateHbz")
-	o := orm.NewOrmUsingDB("data")
-	to, err := o.Begin()
-	if err != nil {
-		return
-	}
-	defer func() {
-		if err != nil {
-			fmt.Println("AddCalculateHbz,Err:" + err.Error())
-			_ = to.Rollback()
-		} else {
-			_ = to.Commit()
-		}
-	}()
-	if req.EdbInfoId <= 0 {
-		edbInfo := new(EdbInfo)
-		edbInfo.Source = utils.DATA_SOURCE_CALCULATE_HBZ
-		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.Formula
-		edbInfo.EdbType = 2
-		newEdbInfoId, tmpErr := to.Insert(edbInfo)
-		if tmpErr != nil {
-			return edbInfoId, tmpErr
-		}
-		edbInfoId = int(newEdbInfoId)
-		//关联关系
-		{
-			calculateMappingItem := new(EdbInfoCalculateMapping)
-			calculateMappingItem.CreateTime = time.Now()
-			calculateMappingItem.ModifyTime = time.Now()
-			calculateMappingItem.Sort = 1
-			calculateMappingItem.EdbCode = edbCode
-			calculateMappingItem.EdbInfoId = edbInfoId
-			calculateMappingItem.FromEdbInfoId = fromEdbInfo.EdbInfoId
-			calculateMappingItem.FromEdbCode = fromEdbInfo.EdbCode
-			calculateMappingItem.FromEdbName = fromEdbInfo.EdbName
-			calculateMappingItem.FromSource = fromEdbInfo.Source
-			calculateMappingItem.FromSourceName = fromEdbInfo.SourceName
-			calculateMappingItem.FromTag = ""
-			calculateMappingItem.Source = edbInfo.Source
-			calculateMappingItem.SourceName = edbInfo.SourceName
-			_, err = to.Insert(calculateMappingItem)
-			if err != nil {
-				return
-			}
-		}
-	} else {
-		edbInfoId = req.EdbInfoId
-		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()
-	}
-
-	edbInfoIdStr := strconv.Itoa(edbInfoId)
-	fmt.Println("edbInfoIdStr:" + edbInfoIdStr)
-	//计算数据
-	var condition string
-	var pars []interface{}
-	condition += " AND edb_info_id=? "
-	if req.EdbInfoId <= 0 {
-		pars = append(pars, req.FromEdbInfoId)
-	} else {
-		pars = append(pars, fromEdbInfo.EdbInfoId)
-	}
-	dataList, err := GetEdbDataListAll(condition, pars, fromEdbInfo.Source, fromEdbInfo.SubSource, 0)
-	if err != nil {
-		return edbInfoId, err
-	}
-
-	addSql := ` INSERT INTO edb_data_calculate_hbz(edb_info_id,edb_code,data_time,value,create_time,modify_time,status,data_timestamp) values `
-	var isAdd bool
-	existMap := make(map[string]string)
-	dataLen := len(dataList)
-	for i := 0; i < dataLen; i++ {
-		j := i + formulaInt
-		if j < dataLen {
-			//当期
-			currentItem := dataList[i]
-			preItem := dataList[j]
-			fmt.Println("preItem.Value:", preItem.Value)
-			if currentItem != nil && preItem != nil && preItem.Value != 0 {
-				existKey := edbCode + currentItem.DataTime
-				if _, ok := existMap[existKey]; !ok {
-					currentDate, _ := time.Parse(utils.FormatDate, currentItem.DataTime)
-					timestamp := currentDate.UnixNano() / 1e6
-					timestampStr := fmt.Sprintf("%d", timestamp)
-					val := HbzDiv(currentItem.Value, preItem.Value)
-					if val != "" {
-						addSql += GetAddSql(edbInfoIdStr, edbCode, currentItem.DataTime, timestampStr, val)
-						isAdd = true
-					}
-				}
-				existMap[existKey] = currentItem.DataTime
-			}
-		}
-	}
-	if isAdd {
-		addSql = strings.TrimRight(addSql, ",")
-		_, err = to.Raw(addSql).Exec()
-		if err != nil {
-			return edbInfoId, err
-		}
-	}
-	return
-}
-
-// 环比值,current:当期,pre:上期 公式: (当期-上期)/上期
-func HbzDiv(current, pre float64) string {
-	if pre == 0 {
-		return ""
-	}
-	currentVal := decimal.NewFromFloat(float64(current))
-	preVal := decimal.NewFromFloat(float64(pre))
-	val, _ := currentVal.Sub(preVal).Div(preVal).Float64()
-	valStr := utils.SubFloatToString(val, 4)
-	return valStr
-}

+ 0 - 149
models/data_manage/edb_info_calculate_hcz.go

@@ -1,149 +0,0 @@
-package data_manage
-
-import (
-	"eta/eta_mobile/utils"
-	"fmt"
-	"github.com/beego/beego/v2/client/orm"
-	"github.com/shopspring/decimal"
-	"strconv"
-	"strings"
-	"time"
-)
-
-// 环差值
-func AddCalculateHcz(req *EdbInfoCalculateBatchSaveReq, fromEdbInfo *EdbInfo, edbCode, uniqueCode string, sysUserId int, sysUserRealName string, formulaInt int) (edbInfoId int, err error) {
-	fmt.Println("AddCalculateHcz")
-	o := orm.NewOrmUsingDB("data")
-	to, err := o.Begin()
-	if err != nil {
-		return
-	}
-	defer func() {
-		if err != nil {
-			fmt.Println("AddCalculateHcz,Err:" + err.Error())
-			_ = to.Rollback()
-		} else {
-			_ = to.Commit()
-		}
-	}()
-	if req.EdbInfoId <= 0 {
-		edbInfo := new(EdbInfo)
-		edbInfo.Source = utils.DATA_SOURCE_CALCULATE_HCZ
-		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.Formula
-		edbInfo.EdbType = 2
-		newEdbInfoId, tmpErr := to.Insert(edbInfo)
-		if tmpErr != nil {
-			return edbInfoId, tmpErr
-		}
-		edbInfoId = int(newEdbInfoId)
-
-		//关联关系
-		{
-			calculateMappingItem := new(EdbInfoCalculateMapping)
-			calculateMappingItem.CreateTime = time.Now()
-			calculateMappingItem.ModifyTime = time.Now()
-			calculateMappingItem.Sort = 1
-			calculateMappingItem.EdbCode = edbCode
-			calculateMappingItem.EdbInfoId = edbInfoId
-			calculateMappingItem.FromEdbInfoId = fromEdbInfo.EdbInfoId
-			calculateMappingItem.FromEdbCode = fromEdbInfo.EdbCode
-			calculateMappingItem.FromEdbName = fromEdbInfo.EdbName
-			calculateMappingItem.FromSource = fromEdbInfo.Source
-			calculateMappingItem.FromSourceName = fromEdbInfo.SourceName
-			calculateMappingItem.FromTag = ""
-			calculateMappingItem.Source = edbInfo.Source
-			calculateMappingItem.SourceName = edbInfo.SourceName
-			_, err = to.Insert(calculateMappingItem)
-			if err != nil {
-				return
-			}
-		}
-	} else {
-		edbInfoId = req.EdbInfoId
-		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()
-	}
-
-	edbInfoIdStr := strconv.Itoa(edbInfoId)
-	fmt.Println("edbInfoIdStr:" + edbInfoIdStr)
-	//计算数据
-	var condition string
-	var pars []interface{}
-	condition += " AND edb_info_id=? "
-	if req.EdbInfoId <= 0 {
-		pars = append(pars, req.FromEdbInfoId)
-	} else {
-		pars = append(pars, fromEdbInfo.EdbInfoId)
-	}
-	dataList, err := GetEdbDataListAll(condition, pars, fromEdbInfo.Source, fromEdbInfo.SubSource, 0)
-	if err != nil {
-		return edbInfoId, err
-	}
-
-	addSql := ` INSERT INTO edb_data_calculate_hcz(edb_info_id,edb_code,data_time,value,create_time,modify_time,status,data_timestamp) values `
-	var isAdd bool
-	existMap := make(map[string]string)
-	dataLen := len(dataList)
-	fmt.Println("dataLen:", dataLen)
-	for i := 0; i < dataLen; i++ {
-		j := i + formulaInt
-		if j < dataLen {
-			//当期
-			currentItem := dataList[i]
-			preItem := dataList[j]
-			if currentItem != nil && preItem != nil {
-				existKey := edbCode + currentItem.DataTime
-				if _, ok := existMap[existKey]; !ok {
-					currentDate, _ := time.Parse(utils.FormatDate, currentItem.DataTime)
-					timestamp := currentDate.UnixNano() / 1e6
-					timestampStr := fmt.Sprintf("%d", timestamp)
-					val := ""
-					if preItem.Value == 0 {
-						val = "0"
-					} else {
-						val = HczDiv(currentItem.Value, preItem.Value)
-					}
-					if val != "" {
-						addSql += GetAddSql(edbInfoIdStr, edbCode, currentItem.DataTime, timestampStr, val)
-						isAdd = true
-					}
-				}
-				existMap[existKey] = currentItem.DataTime
-			}
-		}
-	}
-	if isAdd {
-		addSql = strings.TrimRight(addSql, ",")
-		_, err = to.Raw(addSql).Exec()
-		if err != nil {
-			return edbInfoId, err
-		}
-	}
-	return
-}
-
-// 环差值,current:当期,pre:上期 公式:当期-上期
-func HczDiv(current, pre float64) string {
-	if pre == 0 {
-		return ""
-	}
-	currentVal := decimal.NewFromFloat(current)
-	preVal := decimal.NewFromFloat(pre)
-	val, _ := currentVal.Sub(preVal).Float64()
-	valStr := utils.SubFloatToString(val, 4)
-	return valStr
-}

+ 0 - 387
models/data_manage/edb_info_calculate_ljztbpj.go

@@ -1,387 +0,0 @@
-package data_manage
-
-import (
-	"errors"
-	"eta/eta_mobile/utils"
-	"fmt"
-	"github.com/beego/beego/v2/client/orm"
-	"github.com/shopspring/decimal"
-	"sort"
-	"strings"
-	"time"
-)
-
-// EditCalculateLjztbpj 编辑累计值同比拼接数据
-func EditCalculateLjztbpj(req *EdbInfoCalculateBatchEditReq, nowEdbInfo, firstEdbInfo, secondEdbInfo *EdbInfo) (edbInfoId int, err error) {
-	edbInfoId = req.EdbInfoId
-	o := orm.NewOrmUsingDB("data")
-	to, err := o.Begin()
-	if err != nil {
-		return
-	}
-	defer func() {
-		if err != nil {
-			_ = to.Rollback()
-		} else {
-			_ = to.Commit()
-		}
-	}()
-
-	sql := ``
-
-	var existCondition string
-	var existPars []interface{}
-	existCondition += " AND edb_info_id=? "
-	existPars = append(existPars, edbInfoId)
-
-	//查询出所有的关联指标
-	existList, err := GetEdbInfoCalculateListByCondition(existCondition, existPars)
-	if err != nil {
-		err = errors.New("判断指标是否改变失败,Err:" + err.Error())
-		return
-	}
-
-	var existItemA, existItemB *EdbInfoCalculateMapping
-	for _, existItem := range existList {
-		if existItem.FromTag == "A" {
-			existItemA = existItem
-		} else if existItem.FromTag == "B" {
-			existItemB = existItem
-		}
-	}
-	// 原数据开始计算日期
-	startCalculationDate, _ := time.ParseInLocation(utils.FormatDate, nowEdbInfo.CalculateFormula, time.Local)
-
-	//待拼接指标map
-	pjDataMap := make(map[string]float64)     //需要入库的数据
-	nowEdbDataMap := make(map[string]float64) //当前指标的数据(已经在库里了,不需要重新)
-
-	//拼接指标的日期切片数据
-	pjEdbDataTimeList := make([]string, 0)
-
-	//最近开始的时间
-	lastDateTime := startCalculationDate
-
-	//待拼接指标数据
-	{
-		//如果拼接指标变更了,那么需要删除所有的指标进行重新拼接
-		if existItemA.FromEdbInfoId != firstEdbInfo.EdbInfoId {
-			//删除旧的指标数据
-			{
-				//删除之前的A指标关联关系
-				sql = ` DELETE FROM edb_info_calculate_mapping WHERE edb_info_id = ? and from_edb_info_id = ?`
-				_, err = to.Raw(sql, edbInfoId, existItemA.FromEdbInfoId).Exec()
-				if err != nil {
-					err = errors.New("删除拼接日期之前的指标关联关系失败,Err:" + err.Error())
-					return
-				}
-
-				//如果拼接指标变更了,那么需要删除所有的指标数据
-				tableName := GetEdbDataTableName(nowEdbInfo.Source, nowEdbInfo.SubSource)
-				sql = fmt.Sprintf(` DELETE FROM %s WHERE edb_info_id = ? `, tableName)
-
-				_, err = to.Raw(sql, edbInfoId).Exec()
-				if err != nil {
-					err = errors.New("删除所有的累计值同比拼接指标数据失败,Err:" + err.Error())
-					return
-				}
-			}
-
-			//添加新的指标关系
-			{
-				calculateMappingItem := new(EdbInfoCalculateMapping)
-				calculateMappingItem.CreateTime = time.Now()
-				calculateMappingItem.ModifyTime = time.Now()
-				calculateMappingItem.Sort = 1
-				calculateMappingItem.EdbCode = nowEdbInfo.EdbCode
-				calculateMappingItem.EdbInfoId = edbInfoId
-				calculateMappingItem.FromEdbInfoId = firstEdbInfo.EdbInfoId
-				calculateMappingItem.FromEdbCode = firstEdbInfo.EdbCode
-				calculateMappingItem.FromEdbName = firstEdbInfo.EdbName
-				calculateMappingItem.FromSource = firstEdbInfo.Source
-				calculateMappingItem.FromSourceName = firstEdbInfo.SourceName
-				calculateMappingItem.FromTag = "A"
-				calculateMappingItem.Source = nowEdbInfo.Source
-				calculateMappingItem.SourceName = nowEdbInfo.SourceName
-				_, err = to.Insert(calculateMappingItem)
-				if err != nil {
-					return
-				}
-			}
-
-			var condition string
-			var pars []interface{}
-
-			//获取待拼接指标最近的个12月31日有值的年份
-			condition += " AND data_time like ? AND edb_info_id=? "
-			pars = append(pars, "%12-31", firstEdbInfo.EdbInfoId)
-
-			//获取最新的待拼接指标
-			lastEdbData, tmpErr := GetLastEdbData(condition, pars, firstEdbInfo.Source, firstEdbInfo.SubSource)
-			if tmpErr != nil {
-				return edbInfoId, tmpErr
-			}
-			lastDateTime, _ = time.ParseInLocation(utils.FormatDate, lastEdbData.DataTime, time.Local)
-
-			//获取待拼接指标的数据列表
-			condition = ``
-			pars = make([]interface{}, 0)
-			condition += " AND data_time <= ? AND edb_info_id=? "
-			pars = append(pars, lastEdbData.DataTime, firstEdbInfo.EdbInfoId)
-
-			firstDataList, tmpErr := GetEdbDataListAll(condition, pars, firstEdbInfo.Source, firstEdbInfo.SubSource, 0)
-			if tmpErr != nil {
-				return edbInfoId, tmpErr
-			}
-
-			for _, v := range firstDataList {
-				pjDataMap[v.DataTime] = v.Value
-				pjEdbDataTimeList = append(pjEdbDataTimeList, v.DataTime)
-
-				//将新的数据存入已入库指标map里面,以便后续计算
-				nowEdbDataMap[v.DataTime] = v.Value
-			}
-		} else {
-			// 获取当前指标的所有数据
-			var condition string
-			var pars []interface{}
-			condition += " AND edb_info_id=? and data_time <= ?"
-			pars = append(pars, nowEdbInfo.EdbInfoId, nowEdbInfo.CalculateFormula)
-
-			nowEdbDataList, tmpErr := GetEdbDataListAll(condition, pars, nowEdbInfo.Source, nowEdbInfo.SubSource, 0)
-			if tmpErr != nil {
-				return edbInfoId, tmpErr
-			}
-
-			for _, v := range nowEdbDataList {
-				nowEdbDataMap[v.DataTime] = v.Value
-				pjEdbDataTimeList = append(pjEdbDataTimeList, v.DataTime)
-			}
-		}
-	}
-
-	//同比值指标map
-	tbzEdbDataMap := make(map[string]float64)
-
-	//同比值日期切片列表
-	tbzEdbDataTimeList := make([]string, 0)
-
-	//同比值指标
-	{
-		if existItemB.FromEdbInfoId != secondEdbInfo.EdbInfoId {
-			//删除通过B指标生成的数据
-			{
-				//删除之前的B指标关联关系
-				sql = ` DELETE FROM edb_info_calculate_mapping WHERE edb_info_id = ? and from_edb_info_id = ?`
-				_, err = to.Raw(sql, edbInfoId, existItemB.FromEdbInfoId).Exec()
-				if err != nil {
-					err = errors.New("删除拼接日期之后的指标关联关系失败,Err:" + err.Error())
-					return
-				}
-
-				//如果同比值指标变更了,那么需要删除所有计算出来的指标数据
-				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()
-				if err != nil {
-					err = errors.New("删除计算出来的累计值同比拼接指标数据失败,Err:" + err.Error())
-					return
-				}
-			}
-
-			//添加新的指标关系
-			{
-				calculateMappingItem := new(EdbInfoCalculateMapping)
-				calculateMappingItem.CreateTime = time.Now()
-				calculateMappingItem.ModifyTime = time.Now()
-				calculateMappingItem.Sort = 1
-				calculateMappingItem.EdbCode = nowEdbInfo.EdbCode
-				calculateMappingItem.EdbInfoId = edbInfoId
-				calculateMappingItem.FromEdbInfoId = secondEdbInfo.EdbInfoId
-				calculateMappingItem.FromEdbCode = secondEdbInfo.EdbCode
-				calculateMappingItem.FromEdbName = secondEdbInfo.EdbName
-				calculateMappingItem.FromSource = secondEdbInfo.Source
-				calculateMappingItem.FromSourceName = secondEdbInfo.SourceName
-				calculateMappingItem.FromTag = "B"
-				calculateMappingItem.Source = nowEdbInfo.Source
-				calculateMappingItem.SourceName = nowEdbInfo.SourceName
-				_, err = to.Insert(calculateMappingItem)
-				if err != nil {
-					return
-				}
-			}
-		}
-
-		var condition string
-		var pars []interface{}
-
-		condition += " AND data_time > ? AND edb_info_id = ? "
-		pars = append(pars, lastDateTime, secondEdbInfo.EdbInfoId)
-
-		//同比值指标的数据列表
-		secondDataList, tmpErr := GetEdbDataListAll(condition, pars, secondEdbInfo.Source, secondEdbInfo.SubSource, 0)
-		if tmpErr != nil {
-			return edbInfoId, tmpErr
-		}
-
-		for _, v := range secondDataList {
-			tbzEdbDataMap[v.DataTime] = v.Value
-			tbzEdbDataTimeList = append(tbzEdbDataTimeList, v.DataTime)
-		}
-	}
-
-	sort.Strings(tbzEdbDataTimeList)
-
-	// 遍历现有的数据,判断拼接指标中是否存在该日期数据,如果拼接指标无此数据,那么需要删除该日期数据(日期的判断:需要在开始计算日期之后)
-	removeDateList := make([]string, 0)
-	for nowEdbDate := range nowEdbDataMap {
-		nowEdbDateTime, _ := time.ParseInLocation(utils.FormatDate, nowEdbDate, time.Local)
-		//校验日期 需要 大于 拼接前日期
-		if startCalculationDate.Before(nowEdbDateTime) {
-			if _, ok := tbzEdbDataMap[nowEdbDate]; !ok {
-				// 同比指标中,不存在该日期数据,那么需要移除 现有数据 中该日期的数据
-				removeDateList = append(removeDateList, nowEdbDate)
-			}
-		}
-	}
-
-	//待修改的指标数据map(index:日期,value:值)
-	updateEdbDataMap := make(map[string]float64)
-	for _, v := range tbzEdbDataTimeList {
-		tbzDataTime, _ := time.ParseInLocation(utils.FormatDate, v, time.Local)
-
-		//获取拼接指标上一年同一天的数据
-		var pjDataTime time.Time
-		if tbzDataTime.Month() == 2 {
-			pjDataTime = tbzDataTime.AddDate(0, -11, 0)
-			pjDataTime = time.Date(pjDataTime.Year(), pjDataTime.Month(), 1, 0, 0, 0, 0, time.Now().Location()).AddDate(0, 0, -1)
-		} else {
-			pjDataTime = tbzDataTime.AddDate(-1, 0, 0)
-		}
-
-		//校验现有数据中,是否存在该日期的数据,如果存在的话,那么就要去校验 最新计算数据 与 现有数据 是否一致
-		if nowEdbDataValue, isHas := nowEdbDataMap[v]; isHas {
-			//获取去年今日的数据,获取到后,然后是去修改该日期的数据
-			if lastYearEdbDataValue, ok := nowEdbDataMap[pjDataTime.Format(utils.FormatDate)]; ok {
-				tbzDataValue := tbzEdbDataMap[v] //同比值
-				currValue := lastYearEdbDataValue * (1 + tbzDataValue/100)
-				currValue, _ = decimal.NewFromFloat(currValue).Truncate(4).Float64() //保留4位小数
-				//如果计算出来的值与库里面的值不匹配,那么就去修改该值
-				if nowEdbDataValue != currValue {
-					//将计算后的数据存入待拼接指标map里面,以便后续计算
-					updateEdbDataMap[v] = currValue
-				}
-			}
-		} else {
-			//因为 现有数据中 不存在该日期数据,那么需要做新增数据处理
-
-			//如果去年今日存在该数据,那么就去计算当前的数据
-			if pjDataValue, ok := nowEdbDataMap[pjDataTime.Format(utils.FormatDate)]; ok {
-				tbzDataValue := tbzEdbDataMap[v] //同比值
-				currValue := pjDataValue * (1 + tbzDataValue/100)
-
-				currValue, _ = decimal.NewFromFloat(currValue).Truncate(4).Float64()
-				//将计算后的数据存入已入库指标map里面,以便后续计算
-				nowEdbDataMap[v] = currValue
-
-				//将计算后的数据存入待拼接指标map里面,以便后续入库
-				pjDataMap[v] = currValue
-				pjEdbDataTimeList = append(pjEdbDataTimeList, v)
-			}
-		}
-	}
-
-	//新增的数据入库
-	{
-		addDataList := make([]*EdbDataCalculateLjztbpj, 0)
-		for dataTime, dataValue := range pjDataMap {
-			//时间戳
-			currentDate, _ := time.Parse(utils.FormatDate, dataTime)
-			timestamp := currentDate.UnixNano() / 1e6
-
-			edbDataLjztbpj := &EdbDataCalculateLjztbpj{
-				EdbInfoId:     edbInfoId,
-				EdbCode:       nowEdbInfo.EdbCode,
-				DataTime:      dataTime,
-				Value:         dataValue,
-				Status:        1,
-				CreateTime:    time.Now(),
-				ModifyTime:    time.Now(),
-				DataTimestamp: timestamp,
-			}
-			addDataList = append(addDataList, edbDataLjztbpj)
-		}
-
-		tmpAddDataList := make([]*EdbDataCalculateLjztbpj, 0)
-		for _, v := range addDataList {
-			tmpAddDataList = append(tmpAddDataList, v)
-
-			if len(tmpAddDataList) >= 200 {
-				_, tmpErr := to.InsertMulti(len(tmpAddDataList), tmpAddDataList)
-				if tmpErr != nil {
-					err = tmpErr
-					return
-				}
-				//重新初始化需要加入的数据切片
-				tmpAddDataList = make([]*EdbDataCalculateLjztbpj, 0)
-			}
-		}
-		//最后如果还有需要新增的数据,那么就统一入库
-		if len(tmpAddDataList) > 0 {
-			_, tmpErr := to.InsertMulti(len(tmpAddDataList), tmpAddDataList)
-			if tmpErr != nil {
-				err = tmpErr
-				return
-			}
-		}
-	}
-
-	//删除已经不存在的累计同比拼接指标数据(由于同比值当日的数据删除了)
-	{
-		if len(removeDateList) > 0 {
-			removeDateStr := strings.Join(removeDateList, `","`)
-			removeDateStr = `"` + removeDateStr + `"`
-			//如果拼接指标变更了,那么需要删除所有的指标数据
-			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()
-			if err != nil {
-				err = errors.New("删除不存在的累计值同比拼接指标数据失败,Err:" + err.Error())
-				return
-			}
-		}
-	}
-
-	//修改现有的数据中对应的值
-	{
-		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)
-
-			_, err = to.Raw(sql, edbInfoId).Exec()
-			if err != nil {
-				err = errors.New("更新现有的累计值同比拼接指标数据失败,Err:" + err.Error())
-				return
-			}
-		}
-	}
-
-	//修改指标信息
-	sql = ` UPDATE  edb_info SET
-			  edb_name =?,
-			  edb_name_source=?,
-			  frequency = ?,
-			  unit = ?,
-			  classify_id = ?, 
-			  calculate_formula=?,
-			  modify_time = NOW()
-			WHERE edb_info_id = ? `
-	_, err = to.Raw(sql, req.EdbName, req.EdbName, req.Frequency, req.Unit, req.ClassifyId, lastDateTime.Format(utils.FormatDate), edbInfoId).Exec()
-	if err != nil {
-		return
-	}
-
-	return
-}

+ 0 - 210
models/data_manage/edb_info_calculate_ljzzy.go

@@ -1,210 +0,0 @@
-package data_manage
-
-import (
-	"eta/eta_mobile/utils"
-	"fmt"
-	"github.com/beego/beego/v2/client/orm"
-	"github.com/shopspring/decimal"
-	"strconv"
-	"strings"
-	"time"
-)
-
-// 累计值转月
-func AddCalculateLjzzy(req *EdbInfoCalculateBatchSaveReq, fromEdbInfo *EdbInfo, edbCode, uniqueCode 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_LJZZY
-		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.Formula
-		edbInfo.EdbType = 2
-		newEdbInfoId, tmpErr := to.Insert(edbInfo)
-		if tmpErr != nil {
-			return int(newEdbInfoId), tmpErr
-		}
-		edbInfoId = int(newEdbInfoId)
-
-		//calculateItem := new(EdbInfoCalculateLjzzy)
-		//calculateItem.CreateTime = time.Now()
-		//calculateItem.ModifyTime = time.Now()
-		//calculateItem.Sort = 1
-		//calculateItem.EdbCode = edbCode
-		//calculateItem.EdbInfoId = edbInfoId
-		//calculateItem.FromEdbInfoId = fromEdbInfo.EdbInfoId
-		//calculateItem.FromEdbCode = fromEdbInfo.EdbCode
-		//calculateItem.FromEdbName = fromEdbInfo.EdbName
-		//calculateItem.FromSource = fromEdbInfo.Source
-		//calculateItem.FromSourceName = fromEdbInfo.SourceName
-		//_, err = to.Insert(calculateItem)
-		//if err != nil {
-		//	return edbInfoId, err
-		//}
-		//关联关系
-		{
-			calculateMappingItem := new(EdbInfoCalculateMapping)
-			calculateMappingItem.CreateTime = time.Now()
-			calculateMappingItem.ModifyTime = time.Now()
-			calculateMappingItem.Sort = 1
-			calculateMappingItem.EdbCode = edbCode
-			calculateMappingItem.EdbInfoId = edbInfoId
-			calculateMappingItem.FromEdbInfoId = fromEdbInfo.EdbInfoId
-			calculateMappingItem.FromEdbCode = fromEdbInfo.EdbCode
-			calculateMappingItem.FromEdbName = fromEdbInfo.EdbName
-			calculateMappingItem.FromSource = fromEdbInfo.Source
-			calculateMappingItem.FromSourceName = fromEdbInfo.SourceName
-			calculateMappingItem.FromTag = ""
-			calculateMappingItem.Source = edbInfo.Source
-			calculateMappingItem.SourceName = edbInfo.SourceName
-			_, err = to.Insert(calculateMappingItem)
-			if err != nil {
-				return
-			}
-		}
-	} else {
-		edbInfoId = req.EdbInfoId
-		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()
-	}
-	edbInfoIdStr := strconv.Itoa(edbInfoId)
-	//计算数据
-	var condition string
-	var pars []interface{}
-	condition += " AND edb_info_id=? "
-	if req.EdbInfoId <= 0 {
-		pars = append(pars, req.FromEdbInfoId)
-	} else {
-		pars = append(pars, fromEdbInfo.EdbInfoId)
-	}
-	fmt.Println("EdbInfoId:", req.FromEdbInfoId)
-	dataList, err := GetEdbDataListAll(condition, pars, fromEdbInfo.Source, fromEdbInfo.SubSource, 1)
-	if err != nil {
-		return edbInfoId, err
-	}
-
-	yearMap := make(map[int]map[int]*EdbInfoSearchData)
-	dataLen := len(dataList)
-	for i := 0; i < dataLen; i++ {
-		item := dataList[i]
-		//日其中获取年
-		itemDate, err := time.Parse(utils.FormatDate, item.DataTime)
-		if err != nil {
-			return edbInfoId, err
-		}
-		year := itemDate.Year()
-		month := int(itemDate.Month())
-		if monthMap, yok := yearMap[year]; yok {
-			monthMap[month] = item
-			yearMap[year] = monthMap
-		} else {
-			monthMap = make(map[int]*EdbInfoSearchData)
-			monthMap[month] = item
-			yearMap[year] = monthMap
-		}
-	}
-
-	addSql := ` INSERT INTO edb_data_calculate_ljzzy(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 yk, yv := range yearMap {
-		_, oneMonthOk := yv[1]
-		_, twoMonthOk := yv[2]
-		if !oneMonthOk && !twoMonthOk {
-			continue
-		}
-		for i := 1; i <= 12; i++ {
-			fmt.Println(yk, i, yv[i])
-			dataCurrentItem := yv[i]
-			fmt.Println("i:", i, yk, dataCurrentItem)
-			var date string
-			var val float64
-			if i == 1 || i == 2 {
-				if _, mok := yv[1]; mok { //1月有值
-					if i == 1 {
-						date = dataCurrentItem.DataTime
-						val, _ = decimal.NewFromFloat(dataCurrentItem.Value).Float64() //a.Div(b).Float64()
-					}
-					if i == 2 {
-						dataOneItem := yv[1]
-						if dataCurrentItem != nil {
-							date = dataCurrentItem.DataTime
-							twoMonth := decimal.NewFromFloat(dataCurrentItem.Value)
-							oneMonth := decimal.NewFromFloat(dataOneItem.Value)
-							val, _ = twoMonth.Sub(oneMonth).Float64()
-						} else {
-							continue
-						}
-					}
-				} else { //1月无值
-					dataTwoItem := yv[2]
-					if i == 1 {
-						date = strconv.Itoa(yk) + "-01-31"
-						a := decimal.NewFromFloat(dataTwoItem.Value)
-						b := decimal.NewFromFloat(2.0)
-						val, _ = a.Div(b).Float64()
-					}
-					if i == 2 {
-						date = dataCurrentItem.DataTime
-						a := decimal.NewFromFloat(dataTwoItem.Value)
-						b := decimal.NewFromFloat(2.0)
-						val, _ = a.Div(b).Float64()
-					}
-				}
-			} else {
-				dataPreItem := yv[i-1]
-				if dataCurrentItem != nil && dataPreItem != nil {
-					date = dataCurrentItem.DataTime
-					//val, _ = decimal.NewFromFloat(dataCurrentItem.Value).Sub(decimal.NewFromFloat(dataPreItem.Value)).Float64()
-					a := decimal.NewFromFloat(dataCurrentItem.Value)
-					b := decimal.NewFromFloat(dataPreItem.Value)
-					val, _ = a.Sub(b).Float64()
-				}
-			}
-
-			if date != "" {
-				dataTime, _ := time.Parse(utils.FormatDate, date)
-				timestamp := dataTime.UnixNano() / 1e6
-				timeStr := fmt.Sprintf("%d", timestamp)
-
-				if _, ok := existMap[edbCode+date]; !ok {
-					addSql += GetAddSql(edbInfoIdStr, edbCode, date, timeStr, utils.SubFloatToString(val, 4))
-					isAdd = true
-				}
-				existMap[edbCode+date] = date
-			}
-		}
-	}
-	if isAdd {
-		addSql = strings.TrimRight(addSql, ",")
-		_, err = to.Raw(addSql).Exec()
-		if err != nil {
-			return edbInfoId, err
-		}
-	}
-	return
-}

+ 0 - 173
models/data_manage/edb_info_calculate_nszydpjjs.go

@@ -1,173 +0,0 @@
-package data_manage
-
-import (
-	"eta/eta_mobile/utils"
-	"fmt"
-	"github.com/beego/beego/v2/client/orm"
-	"github.com/shopspring/decimal"
-	"strconv"
-	"strings"
-	"time"
-)
-
-// N数值移动平均计算
-func AddCalculateNszydpjjs(req *EdbInfoCalculateBatchSaveReq, fromEdbInfo *EdbInfo, edbCode, uniqueCode string, sysUserId int, sysUserRealName string, formulaInt int) (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_NSZYDPJJS
-		edbInfo.SourceName = "N数值移动平均计算"
-		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.Formula
-		edbInfo.EdbType = 2
-		newEdbInfoId, tmpErr := to.Insert(edbInfo)
-		if tmpErr != nil {
-			return edbInfoId, tmpErr
-		}
-		edbInfoId = int(newEdbInfoId)
-
-		//calculateItem := new(EdbInfoCalculateNszydpjjs)
-		//calculateItem.CreateTime = time.Now()
-		//calculateItem.ModifyTime = time.Now()
-		//calculateItem.Sort = 1
-		//calculateItem.EdbCode = edbCode
-		//calculateItem.EdbInfoId = edbInfoId
-		//calculateItem.FromEdbInfoId = fromEdbInfo.EdbInfoId
-		//calculateItem.FromEdbCode = fromEdbInfo.EdbCode
-		//calculateItem.FromEdbName = fromEdbInfo.EdbName
-		//calculateItem.FromSource = fromEdbInfo.Source
-		//calculateItem.FromSourceName = fromEdbInfo.SourceName
-		//
-		//_, err = to.Insert(calculateItem)
-		//if err != nil {
-		//	return edbInfoId, err
-		//}
-
-		//关联关系
-		{
-			calculateMappingItem := new(EdbInfoCalculateMapping)
-			calculateMappingItem.CreateTime = time.Now()
-			calculateMappingItem.ModifyTime = time.Now()
-			calculateMappingItem.Sort = 1
-			calculateMappingItem.EdbCode = edbCode
-			calculateMappingItem.EdbInfoId = edbInfoId
-			calculateMappingItem.FromEdbInfoId = fromEdbInfo.EdbInfoId
-			calculateMappingItem.FromEdbCode = fromEdbInfo.EdbCode
-			calculateMappingItem.FromEdbName = fromEdbInfo.EdbName
-			calculateMappingItem.FromSource = fromEdbInfo.Source
-			calculateMappingItem.FromSourceName = fromEdbInfo.SourceName
-			calculateMappingItem.FromTag = ""
-			calculateMappingItem.Source = edbInfo.Source
-			calculateMappingItem.SourceName = edbInfo.SourceName
-			_, err = to.Insert(calculateMappingItem)
-			if err != nil {
-				return
-			}
-		}
-	} else {
-		edbInfoId = req.EdbInfoId
-		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()
-	}
-
-	edbInfoIdStr := strconv.Itoa(edbInfoId)
-	//计算数据
-	var condition string
-	var pars []interface{}
-	condition += " AND edb_info_id=? "
-	if req.EdbInfoId <= 0 {
-		pars = append(pars, req.FromEdbInfoId)
-	} else {
-		pars = append(pars, fromEdbInfo.EdbInfoId)
-	}
-	dataList, err := GetEdbDataListAll(condition, pars, fromEdbInfo.Source, fromEdbInfo.SubSource, 0)
-	if err != nil {
-		return edbInfoId, err
-	}
-	var dateArr []string
-	dataMap := make(map[string]*EdbInfoSearchData)
-	for _, v := range dataList {
-		dateArr = append(dateArr, v.DataTime)
-		dataMap[v.DataTime] = v
-	}
-
-	addSql := ` INSERT INTO edb_data_calculate_nszydpjjs(edb_info_id,edb_code,data_time,value,create_time,modify_time,status,data_timestamp) values `
-	var isAdd bool
-
-	arrLen := len(dateArr)
-	for ak, av := range dateArr {
-		//处理第一个值
-		var valArr []float64
-		if findItem, ok := dataMap[av]; ok {
-			valArr = append(valArr, findItem.Value)
-		} else {
-			continue
-		}
-		if ak+1 != arrLen {
-			//处理除第一个值之外的N-1个值
-			for i := 1; i < formulaInt; i++ {
-				arrIndex := ak + i
-				if arrIndex >= arrLen {
-					break
-				}
-				arrVal := dateArr[arrIndex]
-				if findItem, ok := dataMap[arrVal]; ok {
-					valArr = append(valArr, findItem.Value)
-				} else {
-					continue
-				}
-			}
-		}
-		valArrLen := len(valArr)
-		totalVal := decimal.NewFromFloat(0.00)
-		for _, v := range valArr {
-			newDecimal := decimal.NewFromFloat(v)
-			totalVal = totalVal.Add(newDecimal)
-		}
-		af := totalVal //decimal.NewFromFloat(totalVal)
-		bf := decimal.NewFromFloat(float64(valArrLen))
-		val, _ := af.Div(bf).Float64()
-		currentDate, err := time.Parse(utils.FormatDate, av)
-		if err != nil {
-			return edbInfoId, err
-		}
-
-		timestamp := currentDate.UnixNano() / 1e6
-		timestampStr := fmt.Sprintf("%d", timestamp)
-		valStr := utils.SubFloatToString(val, 4)
-		addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, valStr)
-		isAdd = true
-	}
-
-	if isAdd {
-		addSql = strings.TrimRight(addSql, ",")
-		_, err = to.Raw(addSql).Exec()
-		if err != nil {
-			return edbInfoId, err
-		}
-	}
-	return
-}

+ 0 - 787
models/data_manage/edb_info_calculate_tbz.go

@@ -1,787 +0,0 @@
-package data_manage
-
-import (
-	"errors"
-	"eta/eta_mobile/utils"
-	"fmt"
-	"github.com/beego/beego/v2/client/orm"
-	"github.com/shopspring/decimal"
-	"strconv"
-	"strings"
-	"time"
-)
-
-type EdbInfoCalculateTbz struct {
-	EdbInfoCalculateTbzId int       `orm:"column(edb_info_calculate_tbz_id);pk"`
-	EdbInfoId             int       `description:"指标id"`
-	EdbCode               string    `description:"指标编码"`
-	FromEdbInfoId         int       `description:"计算指标id"`
-	FromEdbCode           string    `description:"计算指标编码"`
-	FromEdbName           string    `description:"计算指标名称"`
-	FromSource            int       `description:"计算指标来源"`
-	FromSourceName        string    `description:"计算指标来源名称"`
-	FromTag               string    `description:"来源指标标签"`
-	Sort                  int       `description:"计算指标名称排序"`
-	CreateTime            time.Time `description:"创建时间"`
-	ModifyTime            time.Time `description:"修改时间"`
-}
-
-// 同比值
-func AddCalculateTbz(req *EdbInfoCalculateBatchSaveReq, fromEdbInfo *EdbInfo, edbCode, uniqueCode string, sysUserId int, sysUserRealName string) (edbInfoId int, err error) {
-	fmt.Println("AddCalculateTbz")
-	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_TBZ
-		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.Formula
-		edbInfo.EdbType = 2
-		newEdbInfoId, tmpErr := to.Insert(edbInfo)
-		if tmpErr != nil {
-			return edbInfoId, tmpErr
-		}
-		edbInfoId = int(newEdbInfoId)
-
-		//calculateItem := new(EdbInfoCalculateTbz)
-		//calculateItem.CreateTime = time.Now()
-		//calculateItem.ModifyTime = time.Now()
-		//calculateItem.Sort = 1
-		//calculateItem.EdbCode = edbCode
-		//calculateItem.EdbInfoId = edbInfoId
-		//calculateItem.FromEdbInfoId = fromEdbInfo.EdbInfoId
-		//calculateItem.FromEdbCode = fromEdbInfo.EdbCode
-		//calculateItem.FromEdbName = fromEdbInfo.EdbName
-		//calculateItem.FromSource = fromEdbInfo.Source
-		//calculateItem.FromSourceName = fromEdbInfo.SourceName
-		//
-		//_, err = to.Insert(calculateItem)
-		//if err != nil {
-		//	return edbInfoId, err
-		//}
-
-		//关联关系
-		{
-			calculateMappingItem := new(EdbInfoCalculateMapping)
-			calculateMappingItem.CreateTime = time.Now()
-			calculateMappingItem.ModifyTime = time.Now()
-			calculateMappingItem.Sort = 1
-			calculateMappingItem.EdbCode = edbCode
-			calculateMappingItem.EdbInfoId = edbInfoId
-			calculateMappingItem.FromEdbInfoId = fromEdbInfo.EdbInfoId
-			calculateMappingItem.FromEdbCode = fromEdbInfo.EdbCode
-			calculateMappingItem.FromEdbName = fromEdbInfo.EdbName
-			calculateMappingItem.FromSource = fromEdbInfo.Source
-			calculateMappingItem.FromSourceName = fromEdbInfo.SourceName
-			calculateMappingItem.FromTag = ""
-			calculateMappingItem.Source = edbInfo.Source
-			calculateMappingItem.SourceName = edbInfo.SourceName
-			_, err = to.Insert(calculateMappingItem)
-			if err != nil {
-				return
-			}
-		}
-
-	} else {
-		edbInfoId = req.EdbInfoId
-		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()
-	}
-
-	edbInfoIdStr := strconv.Itoa(edbInfoId)
-
-	//计算数据
-	var condition string
-	var pars []interface{}
-	condition += " AND edb_info_id=? "
-	if req.EdbInfoId <= 0 {
-		pars = append(pars, req.FromEdbInfoId)
-	} else {
-		pars = append(pars, fromEdbInfo.EdbInfoId)
-	}
-	dataList, err := GetEdbDataListAll(condition, pars, fromEdbInfo.Source, fromEdbInfo.SubSource, 0)
-	if err != nil {
-		return edbInfoId, err
-	}
-	var dateArr []string
-	dataMap := make(map[string]*EdbInfoSearchData)
-	for _, v := range dataList {
-		dateArr = append(dateArr, v.DataTime)
-		dataMap[v.DataTime] = v
-	}
-
-	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
-	existMap := make(map[string]string)
-	for _, av := range dateArr {
-		//fmt.Println(ak, av)
-		currentItem := dataMap[av]
-		if currentItem != nil {
-			//当前日期
-			currentDate, err := time.Parse(utils.FormatDate, av)
-			if err != nil {
-				return edbInfoId, err
-			}
-			//上一年的日期
-			preDate := currentDate.AddDate(-1, 0, 0)
-			preDateStr := preDate.Format(utils.FormatDate)
-			if findItem, ok := dataMap[preDateStr]; ok { //上一年同期找到
-				//dataTime, _ := time.Parse(utils.FormatDate, date)
-				if _, ok := existMap[edbCode+av]; !ok {
-					timestamp := currentDate.UnixNano() / 1e6
-					timestampStr := fmt.Sprintf("%d", timestamp)
-					val := TbzDiv(currentItem.Value, findItem.Value)
-					addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
-					isAdd = true
-					utils.FileLog.Info("同期找到:" + av + ";" + preDateStr)
-				}
-				existMap[edbCode+av] = av
-			} else {
-				if fromEdbInfo.Frequency == "月度" { //向上和向下,各找一个月
-					nextDateDay := preDate
-					preDateDay := preDate
-					for i := 0; i <= 35; i++ {
-						nextDateDayStr := nextDateDay.Format(utils.FormatDate)
-						if findItem, ok := dataMap[nextDateDayStr]; ok { //上一年同期->下一个月找到
-							if _, ok := existMap[edbCode+av]; !ok {
-								timestamp := currentDate.UnixNano() / 1e6
-								timestampStr := fmt.Sprintf("%d", timestamp)
-								val := TbzDiv(currentItem.Value, findItem.Value)
-								addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
-								isAdd = true
-							}
-							existMap[edbCode+av] = av
-							break
-						} else {
-							preDateDayStr := preDateDay.Format(utils.FormatDate)
-							if findItem, ok := dataMap[preDateDayStr]; ok { //上一年同期->上一个月找到
-								if _, ok := existMap[edbCode+av]; !ok {
-									timestamp := currentDate.UnixNano() / 1e6
-									timestampStr := fmt.Sprintf("%d", timestamp)
-									val := TbzDiv(currentItem.Value, findItem.Value)
-
-									addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
-									isAdd = true
-								}
-								existMap[edbCode+av] = av
-								break
-							}
-						}
-						nextDateDay = nextDateDay.AddDate(0, 0, 1)
-						preDateDay = preDateDay.AddDate(0, 0, -1)
-					}
-				} else if fromEdbInfo.Frequency == "季度" || fromEdbInfo.Frequency == "年度" {
-					if findItem, ok := dataMap[preDateStr]; ok { //上一年同期->下一个月找到
-						if _, ok := existMap[edbCode+av]; !ok {
-							timestamp := currentDate.UnixNano() / 1e6
-							timestampStr := fmt.Sprintf("%d", timestamp)
-							val := TbzDiv(currentItem.Value, findItem.Value)
-
-							addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
-							isAdd = true
-						}
-						existMap[edbCode+av] = av
-						break
-					}
-				} else {
-					nextDateDay := preDate
-					preDateDay := preDate
-
-					for i := 0; i < 35; i++ {
-						nextDateDayStr := nextDateDay.Format(utils.FormatDate)
-						if findItem, ok := dataMap[nextDateDayStr]; ok { //上一年同期->下一个月找到
-							if _, ok := existMap[edbCode+av]; !ok {
-								timestamp := currentDate.UnixNano() / 1e6
-								timestampStr := fmt.Sprintf("%d", timestamp)
-								val := TbzDiv(currentItem.Value, findItem.Value)
-								addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
-								isAdd = true
-							}
-							existMap[edbCode+av] = av
-							break
-						} else {
-							preDateDayStr := preDateDay.Format(utils.FormatDate)
-							if findItem, ok := dataMap[preDateDayStr]; ok { //上一年同期->上一个月找到
-								if _, ok := existMap[edbCode+av]; !ok {
-									timestamp := currentDate.UnixNano() / 1e6
-									timestampStr := fmt.Sprintf("%d", timestamp)
-									val := TbzDiv(currentItem.Value, findItem.Value)
-									addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
-									isAdd = true
-								}
-								existMap[edbCode+av] = av
-								break
-							} else {
-								//fmt.Println("pre not find:", preDateStr, "i:", i)
-							}
-						}
-						nextDateDay = nextDateDay.AddDate(0, 0, 1)
-						preDateDay = preDateDay.AddDate(0, 0, -1)
-					}
-				}
-			}
-		}
-	}
-	if isAdd {
-		addSql = strings.TrimRight(addSql, ",")
-		_, err = to.Raw(addSql).Exec()
-		if err != nil {
-			return edbInfoId, err
-		}
-	}
-	return
-}
-
-func GetAddSql(edbInfoId, edbCode, dataTime, timestampStr string, value string) (addSql string) {
-	nowStr := time.Now().Format(utils.FormatDateTime)
-	addSql += "("
-	addSql += edbInfoId + "," + "'" + edbCode + "'" + "," + "'" + dataTime + "'" + "," + value + "," + "'" + nowStr + "'" +
-		"," + "'" + nowStr + "'" + "," + "1"
-	addSql += "," + "'" + timestampStr + "'"
-	addSql += "),"
-	return
-}
-
-func TbzDiv(a, b float64) string {
-	var valStr string
-	if b != 0 {
-		af := decimal.NewFromFloat(float64(a))
-		bf := decimal.NewFromFloat(float64(b))
-		val, _ := af.Div(bf).Float64()
-		val = val - 1
-		valStr = utils.SubFloatToString(val, 4)
-	} else {
-		valStr = "0"
-	}
-	return valStr
-}
-
-// 同比值
-func EditCalculateTbz(req *EdbInfoCalculateBatchEditReq, fromEdbInfo *EdbInfo, edbCode string) (edbInfoId int, err error) {
-	edbInfoId = req.EdbInfoId
-	o := orm.NewOrmUsingDB("data")
-	to, err := o.Begin()
-	if err != nil {
-		return
-	}
-	defer func() {
-		if err != nil {
-			_ = to.Rollback()
-		} else {
-			_ = to.Commit()
-		}
-	}()
-
-	//修改指标信息
-	sql := ` UPDATE  edb_info
-			SET
-			  edb_name =?,
-			  edb_name_source=?,
-			  frequency = ?,
-			  unit = ?,
-			  classify_id = ?,
-			  modify_time = NOW()
-			WHERE edb_info_id = ? `
-	_, err = to.Raw(sql, req.EdbName, req.EdbName, req.Frequency, req.Unit, req.ClassifyId, edbInfoId).Exec()
-	if err != nil {
-		return
-	}
-
-	var existCondition string
-	var existPars []interface{}
-	existCondition += " AND edb_info_id=? "
-	existPars = append(existPars, edbInfoId)
-
-	existCondition += " AND from_edb_info_id=? "
-	existPars = append(existPars, req.FromEdbInfoId)
-
-	//判断计算指标是否被更换
-	count, tmpErr := GetEdbInfoCalculateCountByCondition(req.Source, existCondition, existPars)
-	if tmpErr != nil {
-		err = errors.New("判断指标是否改变失败,Err:" + err.Error())
-		return
-	}
-	if count <= 0 {
-		//删除指标关联计算指标
-		//sql := ` DELETE FROM edb_info_calculate_tbz WHERE edb_info_id = ? `
-		//_, err = to.Raw(sql, edbInfoId).Exec()
-		//if err != nil {
-		//	return
-		//}
-		//
-		//calculateItem := new(EdbInfoCalculateTbz)
-		//calculateItem.CreateTime = time.Now()
-		//calculateItem.ModifyTime = time.Now()
-		//calculateItem.Sort = 1
-		//calculateItem.EdbCode = edbCode
-		//calculateItem.EdbInfoId = edbInfoId
-		//calculateItem.FromEdbInfoId = fromEdbInfo.EdbInfoId
-		//calculateItem.FromEdbCode = fromEdbInfo.EdbCode
-		//calculateItem.FromEdbName = fromEdbInfo.EdbName
-		//calculateItem.FromSource = fromEdbInfo.Source
-		//calculateItem.FromSourceName = fromEdbInfo.SourceName
-		//
-		//_, err = to.Insert(calculateItem)
-		//if err != nil {
-		//	return
-		//}
-
-		//删除,计算指标关联的,基础指标的关联关系
-		sql = ` DELETE FROM edb_info_calculate_mapping WHERE edb_info_id = ? `
-		_, err = to.Raw(sql, edbInfoId).Exec()
-		if err != nil {
-			return edbInfoId, err
-		}
-		//清空原有数据
-		sql = ` DELETE FROM edb_data_calculate_tbz WHERE edb_info_id = ? `
-		_, err = to.Raw(sql, edbInfoId).Exec()
-		if err != nil {
-			return edbInfoId, err
-		}
-		//关联关系
-		{
-			calculateMappingItem := new(EdbInfoCalculateMapping)
-			calculateMappingItem.CreateTime = time.Now()
-			calculateMappingItem.ModifyTime = time.Now()
-			calculateMappingItem.Sort = 1
-			calculateMappingItem.EdbCode = edbCode
-			calculateMappingItem.EdbInfoId = edbInfoId
-			calculateMappingItem.FromEdbInfoId = fromEdbInfo.EdbInfoId
-			calculateMappingItem.FromEdbCode = fromEdbInfo.EdbCode
-			calculateMappingItem.FromEdbName = fromEdbInfo.EdbName
-			calculateMappingItem.FromSource = fromEdbInfo.Source
-			calculateMappingItem.FromSourceName = fromEdbInfo.SourceName
-			calculateMappingItem.FromTag = ""
-			calculateMappingItem.Source = utils.DATA_SOURCE_CALCULATE_TBZ
-			calculateMappingItem.SourceName = "同比值"
-			_, err = to.Insert(calculateMappingItem)
-			if err != nil {
-				return
-			}
-		}
-
-		edbInfoIdStr := strconv.Itoa(edbInfoId)
-
-		//计算数据
-		var condition string
-		var pars []interface{}
-		condition += " AND edb_info_id=? "
-		pars = append(pars, req.FromEdbInfoId)
-		fmt.Println("EdbInfoId:", req.FromEdbInfoId)
-		dataList, err := GetEdbDataListAll(condition, pars, fromEdbInfo.Source, fromEdbInfo.SubSource, 0)
-		if err != nil {
-			return edbInfoId, err
-		}
-		var dateArr []string
-		dataMap := make(map[string]*EdbInfoSearchData)
-		for _, v := range dataList {
-			dateArr = append(dateArr, v.DataTime)
-			dataMap[v.DataTime] = v
-		}
-
-		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
-		for _, av := range dateArr {
-			currentItem := dataMap[av]
-			if currentItem != nil {
-				//当前日期
-				currentDate, err := time.Parse(utils.FormatDate, av)
-				if err != nil {
-					return edbInfoId, 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)
-					addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
-					isAdd = true
-					utils.FileLog.Info("同期找到:" + av + ";" + preDateStr)
-					continue
-				} else {
-					if fromEdbInfo.Frequency == "月度" { //向上和向下,各找一个月
-						nextDateDay := preDate.AddDate(0, 1, 0)
-						nextDateDayStr := nextDateDay.Format(utils.FormatDate)
-
-						preDateDay := preDate.AddDate(0, -1, 0)
-						preDateDayStr := preDateDay.Format(utils.FormatDate)
-
-						for i := 0; i <= 6; 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)
-
-								addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
-								isAdd = true
-								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)
-
-									addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
-									isAdd = true
-									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)
-
-							addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
-							isAdd = true
-							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)
-
-								addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
-								isAdd = true
-								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)
-
-									addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
-									isAdd = true
-									break
-								}
-							}
-						}
-					}
-				}
-			}
-		}
-		if isAdd {
-			addSql = strings.TrimRight(addSql, ",")
-			_, err = to.Raw(addSql).Exec()
-			if err != nil {
-				return edbInfoId, err
-			}
-		}
-	}
-	return
-}
-
-// 刷新同比值数据
-func RefreshCalculateTbz(edbInfoId 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, fromEdbInfo.SubSource, 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
-	}
-
-	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
-	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)
-
-				count, err := GetEdbDataCalculateTbzByCodeAndDate(edbCode, av)
-				if err != nil && err.Error() != utils.ErrNoRow() {
-					return err
-				}
-				if count <= 0 {
-					addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
-					isAdd = true
-				} else {
-					err = ModifyEdbDataCalculateTbz(int64(edbInfoId), av, val)
-					if err != nil {
-						return err
-					}
-				}
-				utils.FileLog.Info("同期找到:" + av + ";" + preDateStr)
-				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)
-							fmt.Println(currentItem.Value, findItem.Value)
-							val := TbzDiv(currentItem.Value, findItem.Value)
-
-							count, err := GetEdbDataCalculateTbzByCodeAndDate(edbCode, av)
-							if err != nil && err.Error() != utils.ErrNoRow() {
-								return err
-							}
-							if count <= 0 {
-								addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
-								isAdd = true
-							} else {
-								err = ModifyEdbDataCalculateTbz(int64(edbInfoId), av, val)
-								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)
-
-								count, err := GetEdbDataCalculateTbzByCodeAndDate(edbCode, av)
-								if err != nil && err.Error() != utils.ErrNoRow() {
-									return err
-								}
-								if count <= 0 {
-									addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
-									isAdd = true
-								} else {
-									err = ModifyEdbDataCalculateTbz(int64(edbInfoId), av, val)
-									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)
-
-						count, err := GetEdbDataCalculateTbzByCodeAndDate(edbCode, av)
-						if err != nil && err.Error() != utils.ErrNoRow() {
-							return err
-						}
-						if count <= 0 {
-							addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
-							isAdd = true
-						} else {
-							err = ModifyEdbDataCalculateTbz(int64(edbInfoId), av, val)
-							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)
-
-							count, err := GetEdbDataCalculateTbzByCodeAndDate(edbCode, av)
-							if err != nil && err.Error() != utils.ErrNoRow() {
-								return err
-							}
-							if count <= 0 {
-								addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
-								isAdd = true
-							} else {
-								err = ModifyEdbDataCalculateTbz(int64(edbInfoId), av, val)
-								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)
-
-								count, err := GetEdbDataCalculateTbzByCodeAndDate(edbCode, av)
-								if err != nil && err.Error() != utils.ErrNoRow() {
-									return err
-								}
-								if count <= 0 {
-									addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
-									isAdd = true
-								} else {
-									err = ModifyEdbDataCalculateTbz(int64(edbInfoId), av, val)
-									if err != nil {
-										return err
-									}
-								}
-								break
-							}
-						}
-					}
-				}
-			}
-		}
-	}
-	if isAdd {
-		addSql = strings.TrimRight(addSql, ",")
-		_, err = to.Raw(addSql).Exec()
-		if err != nil {
-			return err
-		}
-	}
-	return
-}
-
-type EdbInfoCalculateTbzDetail struct {
-	EdbInfoCalculateTbzId int       `orm:"column(edb_info_calculate_tbz_id);pk"`
-	EdbInfoId             int       `description:"指标id"`
-	EdbCode               string    `description:"指标编码"`
-	FromEdbInfoId         int       `description:"计算指标id"`
-	FromEdbCode           string    `description:"计算指标编码"`
-	FromEdbName           string    `description:"计算指标名称"`
-	FromSource            int       `description:"计算指标来源"`
-	FromSourceName        string    `description:"计算指标来源名称"`
-	FromTag               string    `description:"来源指标标签"`
-	Sort                  int       `description:"计算指标名称排序"`
-	CreateTime            time.Time `description:"创建时间"`
-	ModifyTime            time.Time `description:"修改时间"`
-	StartDate             string    `description:"开始日期"`
-	EndDate               string    `description:"结束日期"`
-}
-
-func GetEdbInfoCalculateTbzDetail(edbInfoId int) (item *EdbInfoCalculateTbzDetail, err error) {
-	o := orm.NewOrmUsingDB("data")
-	sql := ` SELECT a.*,b.start_date,b.end_date FROM edb_info_calculate_mapping AS a
-			INNER JOIN edb_info AS b ON a.from_edb_info_id=b.edb_info_id
-			WHERE a.edb_info_id=? `
-	err = o.Raw(sql, edbInfoId).QueryRow(&item)
-	return
-}
-
-func GetEdbDataCalculateTbzByCodeAndDate(edbCode string, startDate string) (count int, err error) {
-	o := orm.NewOrmUsingDB("data")
-	sql := ` SELECT COUNT(1) AS count FROM edb_data_calculate_tbz WHERE edb_code=? AND data_time=? `
-	err = o.Raw(sql, edbCode, startDate).QueryRow(&count)
-	return
-}
-
-func ModifyEdbDataCalculateTbz(edbInfoId int64, dataTime, value string) (err error) {
-	o := orm.NewOrmUsingDB("data")
-	sql := ` UPDATE edb_data_calculate_tbz SET value=?,modify_time=NOW() WHERE edb_info_id=? AND data_time=? `
-	_, err = o.Raw(sql, value, edbInfoId, dataTime).Exec()
-	return
-}

+ 0 - 256
models/data_manage/edb_info_calculate_tcz.go

@@ -1,256 +0,0 @@
-package data_manage
-
-import (
-	"eta/eta_mobile/utils"
-	"fmt"
-	"github.com/beego/beego/v2/client/orm"
-	"github.com/shopspring/decimal"
-	"strconv"
-	"strings"
-	"time"
-)
-
-// 同差值
-func AddCalculateTcz(req *EdbInfoCalculateBatchSaveReq, fromEdbInfo *EdbInfo, edbCode, uniqueCode 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 {
-			fmt.Println("err:", err.Error())
-			_ = to.Rollback()
-		} else {
-			_ = to.Commit()
-		}
-	}()
-	fmt.Println("req.EdbInfoId:", req.EdbInfoId)
-	if req.EdbInfoId <= 0 {
-		edbInfo := new(EdbInfo)
-		edbInfo.Source = utils.DATA_SOURCE_CALCULATE_TCZ
-		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.Formula
-		edbInfo.EdbType = 2
-		newEdbInfoId, tmpErr := to.Insert(edbInfo)
-		if tmpErr != nil {
-			return edbInfoId, tmpErr
-		}
-		edbInfoId = int(newEdbInfoId)
-
-		//calculateItem := new(EdbInfoCalculateTcz)
-		//calculateItem.CreateTime = time.Now()
-		//calculateItem.ModifyTime = time.Now()
-		//calculateItem.Sort = 1
-		//calculateItem.EdbCode = edbCode
-		//calculateItem.EdbInfoId = edbInfoId
-		//calculateItem.FromEdbInfoId = fromEdbInfo.EdbInfoId
-		//calculateItem.FromEdbCode = fromEdbInfo.EdbCode
-		//calculateItem.FromEdbName = fromEdbInfo.EdbName
-		//calculateItem.FromSource = fromEdbInfo.Source
-		//calculateItem.FromSourceName = fromEdbInfo.SourceName
-		//
-		//_, err = to.Insert(calculateItem)
-		//if err != nil {
-		//	return edbInfoId, err
-		//}
-
-		//关联关系
-		{
-			calculateMappingItem := new(EdbInfoCalculateMapping)
-			calculateMappingItem.CreateTime = time.Now()
-			calculateMappingItem.ModifyTime = time.Now()
-			calculateMappingItem.Sort = 1
-			calculateMappingItem.EdbCode = edbCode
-			calculateMappingItem.EdbInfoId = edbInfoId
-			calculateMappingItem.FromEdbInfoId = fromEdbInfo.EdbInfoId
-			calculateMappingItem.FromEdbCode = fromEdbInfo.EdbCode
-			calculateMappingItem.FromEdbName = fromEdbInfo.EdbName
-			calculateMappingItem.FromSource = fromEdbInfo.Source
-			calculateMappingItem.FromSourceName = fromEdbInfo.SourceName
-			calculateMappingItem.FromTag = ""
-			calculateMappingItem.Source = edbInfo.Source
-			calculateMappingItem.SourceName = edbInfo.SourceName
-			_, err = to.Insert(calculateMappingItem)
-			if err != nil {
-				return
-			}
-		}
-	} else {
-		edbInfoId = req.EdbInfoId
-		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)
-		_, err = to.Raw(deleteSql, req.EdbInfoId).Exec()
-		if err != nil {
-			return edbInfoId, err
-		}
-	}
-
-	edbInfoIdStr := strconv.Itoa(edbInfoId)
-
-	//计算数据
-	var condition string
-	var pars []interface{}
-	condition += " AND edb_info_id=? "
-	if req.EdbInfoId <= 0 {
-		pars = append(pars, req.FromEdbInfoId)
-	} else {
-		pars = append(pars, fromEdbInfo.EdbInfoId)
-	}
-
-	fmt.Println("EdbInfoId:", req.FromEdbInfoId)
-	dataList, err := GetEdbDataListAll(condition, pars, fromEdbInfo.Source, fromEdbInfo.SubSource, 0)
-	if err != nil {
-		return edbInfoId, err
-	}
-	var dateArr []string
-	dataMap := make(map[string]*EdbInfoSearchData)
-	for _, v := range dataList {
-		dateArr = append(dateArr, v.DataTime)
-		dataMap[v.DataTime] = v
-	}
-	fmt.Println("Frequency:", fromEdbInfo.Frequency)
-	addSql := ` INSERT INTO edb_data_calculate_tcz(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 _, av := range dateArr {
-		//fmt.Println("dateArr:", ak, av)
-		currentItem := dataMap[av]
-		if currentItem != nil {
-			//当前日期
-			currentDate, err := time.Parse(utils.FormatDate, av)
-			if err != nil {
-				return edbInfoId, err
-			}
-			//上一年的日期
-			preDate := currentDate.AddDate(-1, 0, 0)
-			preDateStr := preDate.Format(utils.FormatDate)
-			if findItem, ok := dataMap[preDateStr]; ok { //上一年同期找到
-				//dataTime, _ := time.Parse(utils.FormatDate, date)
-				if _, ok := existMap[edbCode+av]; !ok {
-					timestamp := currentDate.UnixNano() / 1e6
-					timestampStr := fmt.Sprintf("%d", timestamp)
-
-					val := TczSub(currentItem.Value, findItem.Value)
-					addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
-					isAdd = true
-				}
-				existMap[edbCode+av] = av
-			} else {
-				if fromEdbInfo.Frequency == "月度" { //向上和向下,各找一个月
-					nextDateDay := preDate
-					preDateDay := preDate
-					for i := 0; i <= 35; i++ {
-						nextDateDayStr := nextDateDay.Format(utils.FormatDate)
-						if findItem, ok := dataMap[nextDateDayStr]; ok { //下一年同期->下一个月找到
-							if _, ok := existMap[edbCode+av]; !ok {
-								timestamp := currentDate.UnixNano() / 1e6
-								timestampStr := fmt.Sprintf("%d", timestamp)
-								val := TczSub(currentItem.Value, findItem.Value)
-
-								addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
-								isAdd = true
-							}
-							existMap[edbCode+av] = av
-							break
-						} else {
-							preDateDayStr := preDateDay.Format(utils.FormatDate)
-							if findItem, ok := dataMap[preDateDayStr]; ok { //上一年同期->上一个月找到
-								if _, ok := existMap[edbCode+av]; !ok {
-									timestamp := currentDate.UnixNano() / 1e6
-									timestampStr := fmt.Sprintf("%d", timestamp)
-									val := TczSub(currentItem.Value, findItem.Value)
-
-									addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
-									isAdd = true
-								}
-								existMap[edbCode+av] = av
-								break
-							}
-						}
-						nextDateDay = nextDateDay.AddDate(0, 0, 1)
-						preDateDay = preDateDay.AddDate(0, 0, -1)
-					}
-				} else if fromEdbInfo.Frequency == "季度" || fromEdbInfo.Frequency == "年度" {
-					if findItem, ok := dataMap[preDateStr]; ok { //上一年同期->下一个月找到
-						if _, ok := existMap[edbCode+av]; !ok {
-							timestamp := currentDate.UnixNano() / 1e6
-							timestampStr := fmt.Sprintf("%d", timestamp)
-							val := TczSub(currentItem.Value, findItem.Value)
-							addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
-							isAdd = true
-						}
-						existMap[edbCode+av] = av
-						break
-					}
-				} else {
-					nextDateDay := preDate
-					preDateDay := preDate
-					for i := 0; i < 35; i++ {
-						nextDateDayStr := nextDateDay.Format(utils.FormatDate)
-						if findItem, ok := dataMap[nextDateDayStr]; ok { //上一年同期->下一个月找到
-							if _, ok := existMap[edbCode+av]; !ok {
-								timestamp := currentDate.UnixNano() / 1e6
-								timestampStr := fmt.Sprintf("%d", timestamp)
-								val := TczSub(currentItem.Value, findItem.Value)
-
-								addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
-								isAdd = true
-							}
-							existMap[edbCode+av] = av
-							break
-						} else {
-							preDateDayStr := preDateDay.Format(utils.FormatDate)
-							if findItem, ok := dataMap[preDateDayStr]; ok { //上一年同期->上一个月找到
-								if _, ok := existMap[edbCode+av]; !ok {
-									timestamp := currentDate.UnixNano() / 1e6
-									timestampStr := fmt.Sprintf("%d", timestamp)
-									val := TczSub(currentItem.Value, findItem.Value)
-
-									addSql += GetAddSql(edbInfoIdStr, edbCode, av, timestampStr, val)
-									isAdd = true
-								}
-								existMap[edbCode+av] = av
-								break
-							} else {
-
-							}
-						}
-						nextDateDay = nextDateDay.AddDate(0, 0, 1)
-						preDateDay = preDateDay.AddDate(0, 0, -1)
-					}
-				}
-			}
-		}
-	}
-	if isAdd {
-		addSql = strings.TrimRight(addSql, ",")
-		_, err = to.Raw(addSql).Exec()
-		if err != nil {
-			return edbInfoId, err
-		}
-	}
-	return
-}
-
-func TczSub(a, b float64) string {
-	af := decimal.NewFromFloat(float64(a))
-	fmt.Println(af)
-	bf := decimal.NewFromFloat(float64(b))
-	val, _ := af.Sub(bf).Float64()
-	valStr := utils.SubFloatToString(val, 4)
-	return valStr
-}

+ 0 - 286
models/data_manage/edb_info_calculate_zjpj.go

@@ -1,286 +0,0 @@
-package data_manage
-
-import (
-	"errors"
-	"eta/eta_mobile/utils"
-	"github.com/beego/beego/v2/client/orm"
-	"time"
-)
-
-// EditCalculateZjpj 编辑直接拼接数据
-func EditCalculateZjpj(req *EdbInfoCalculateBatchEditReq, nowEdbInfo, firstEdbInfo, secondEdbInfo *EdbInfo) (edbInfoId int, err error) {
-	edbInfoId = req.EdbInfoId
-	o := orm.NewOrmUsingDB("data")
-	to, err := o.Begin()
-	if err != nil {
-		return
-	}
-	defer func() {
-		if err != nil {
-			_ = to.Rollback()
-		} else {
-			_ = to.Commit()
-		}
-	}()
-
-	//修改指标信息
-	sql := ` UPDATE  edb_info SET
-			  edb_name =?,
-			  edb_name_source=?,
-			  frequency = ?,
-			  unit = ?,
-			  classify_id = ?, 
-			  calculate_formula=?,
-			  modify_time = NOW()
-			WHERE edb_info_id = ? `
-	_, err = to.Raw(sql, req.EdbName, req.EdbName, req.Frequency, req.Unit, req.ClassifyId, req.Formula, edbInfoId).Exec()
-	if err != nil {
-		return
-	}
-
-	var existCondition string
-	var existPars []interface{}
-	existCondition += " AND edb_info_id=? "
-	existPars = append(existPars, edbInfoId)
-
-	//查询出所有的关联指标
-	existList, err := GetEdbInfoCalculateListByCondition(existCondition, existPars)
-	if err != nil {
-		err = errors.New("判断指标是否改变失败,Err:" + err.Error())
-		return
-	}
-
-	var existItemA, existItemB *EdbInfoCalculateMapping
-	for _, existItem := range existList {
-		if existItem.FromTag == "A" {
-			existItemA = existItem
-		} else if existItem.FromTag == "B" {
-			existItemB = existItem
-		}
-	}
-
-	addDataList := make([]*EdbDataCalculateZjpj, 0)
-	firstDataList := make([]*EdbInfoSearchData, 0)
-	secondDataList := make([]*EdbInfoSearchData, 0)
-
-	//如果 之前的拼接日期 与 现在的拼接日期 不一致的话,需要做以下处理
-	nowFormulaDate, _ := time.ParseInLocation(utils.FormatDate, nowEdbInfo.CalculateFormula, time.Local)
-	reqFormulaDate, _ := time.ParseInLocation(utils.FormatDate, req.Formula, time.Local)
-
-	//如果前后选择的日期不一致,那么需要删除一部分数据
-	if nowEdbInfo.CalculateFormula != req.Formula {
-		var startDate, endDate time.Time
-		//如果当前选择的日期 小于 之前选择的日期
-		if reqFormulaDate.Before(nowFormulaDate) {
-			startDate = reqFormulaDate
-			endDate = nowFormulaDate
-		} else { //如果当前选择的日期 大于 之前选择的日期
-			startDate = nowFormulaDate
-			endDate = reqFormulaDate
-		}
-		//删除 之前日期 与 当前日期 之间的指标数据
-		sql = ` DELETE FROM edb_data_calculate_zjpj WHERE edb_info_id = ? and data_time >= ? and data_time < ?`
-		_, err = to.Raw(sql, edbInfoId, startDate, endDate).Exec()
-		if err != nil {
-			err = errors.New("删除 之前日期 与 当前日期 之间的指标数据失败,Err:" + err.Error())
-			return
-		}
-	}
-	//第一个指标数据
-	{
-		var condition string
-		var pars []interface{}
-		if existItemA.FromEdbInfoId != firstEdbInfo.EdbInfoId {
-			//删除之前的A指标关联关系
-			sql = ` DELETE FROM edb_info_calculate_mapping WHERE edb_info_id = ? and from_edb_info_id = ?`
-			_, err = to.Raw(sql, edbInfoId, existItemA.FromEdbInfoId).Exec()
-			if err != nil {
-				err = errors.New("删除拼接日期之前的指标关联关系失败,Err:" + err.Error())
-				return
-			}
-
-			//删除之前所有的A指标数据
-			sql = ` DELETE FROM edb_data_calculate_zjpj WHERE edb_info_id = ? and data_time < ?`
-			_, err = to.Raw(sql, edbInfoId, req.Formula).Exec()
-			if err != nil {
-				err = errors.New("删除拼接日期之前的数据失败,Err:" + err.Error())
-				return
-			}
-
-			//获取第一个指标的数据列表
-			condition += " AND data_time < ? AND edb_info_id=? "
-			pars = append(pars, req.Formula, firstEdbInfo.EdbInfoId)
-
-			tmpFirstDataList, tmpErr := GetEdbDataListAll(condition, pars, firstEdbInfo.Source, firstEdbInfo.SubSource, 0)
-			if tmpErr != nil {
-				return edbInfoId, tmpErr
-			}
-			firstDataList = tmpFirstDataList
-
-			//添加新的指标关系
-			{
-				calculateMappingItem := new(EdbInfoCalculateMapping)
-				calculateMappingItem.CreateTime = time.Now()
-				calculateMappingItem.ModifyTime = time.Now()
-				calculateMappingItem.Sort = 1
-				calculateMappingItem.EdbCode = nowEdbInfo.EdbCode
-				calculateMappingItem.EdbInfoId = edbInfoId
-				calculateMappingItem.FromEdbInfoId = firstEdbInfo.EdbInfoId
-				calculateMappingItem.FromEdbCode = firstEdbInfo.EdbCode
-				calculateMappingItem.FromEdbName = firstEdbInfo.EdbName
-				calculateMappingItem.FromSource = firstEdbInfo.Source
-				calculateMappingItem.FromSourceName = firstEdbInfo.SourceName
-				calculateMappingItem.FromTag = "A"
-				calculateMappingItem.Source = nowEdbInfo.Source
-				calculateMappingItem.SourceName = nowEdbInfo.SourceName
-				_, err = to.Insert(calculateMappingItem)
-				if err != nil {
-					return
-				}
-			}
-		} else {
-			if req.Formula != nowEdbInfo.CalculateFormula {
-				//获取第一个指标的数据列表
-				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, firstEdbInfo.SubSource, 0)
-				if tmpErr != nil {
-					return edbInfoId, tmpErr
-				}
-				firstDataList = tmpFirstDataList
-			}
-		}
-
-		//待插入数据
-		for _, v := range firstDataList {
-			//时间戳
-			currentDate, _ := time.Parse(utils.FormatDate, v.DataTime)
-			timestamp := currentDate.UnixNano() / 1e6
-
-			edbDataZjpj := &EdbDataCalculateZjpj{
-				EdbInfoId:     edbInfoId,
-				EdbCode:       nowEdbInfo.EdbCode,
-				DataTime:      v.DataTime,
-				Value:         v.Value,
-				Status:        1,
-				CreateTime:    time.Now(),
-				ModifyTime:    time.Now(),
-				DataTimestamp: timestamp,
-			}
-			addDataList = append(addDataList, edbDataZjpj)
-		}
-	}
-
-	//第二个指标数据
-	{
-		var condition string
-		var pars []interface{}
-
-		if existItemB.FromEdbInfoId != secondEdbInfo.EdbInfoId {
-			//删除之前的B指标关联关系
-			sql = ` DELETE FROM edb_info_calculate_mapping WHERE edb_info_id = ? and from_edb_info_id = ?`
-			_, err = to.Raw(sql, edbInfoId, existItemB.FromEdbInfoId).Exec()
-			if err != nil {
-				err = errors.New("删除拼接日期之后的指标关联关系失败,Err:" + err.Error())
-				return
-			}
-
-			//删除历史拼接日期之前所有的B指标数据
-			sql = ` DELETE FROM edb_data_calculate_zjpj WHERE edb_info_id = ? and data_time >= ?`
-			_, err = to.Raw(sql, edbInfoId, nowEdbInfo.CalculateFormula).Exec()
-			if err != nil {
-				err = errors.New("删除历史拼接日期之后的数据失败,Err:" + err.Error())
-				return
-			}
-
-			//第二个指标的数据列表
-			condition = " AND data_time >= ?  AND edb_info_id=? "
-			pars = append(pars, reqFormulaDate, secondEdbInfo.EdbInfoId)
-			tmpSecondDataList, tmpErr := GetEdbDataListAll(condition, pars, secondEdbInfo.Source, secondEdbInfo.SubSource, 0)
-			if tmpErr != nil {
-				return edbInfoId, tmpErr
-			}
-			secondDataList = tmpSecondDataList
-
-			//添加新的指标关系
-			{
-				calculateMappingItem := new(EdbInfoCalculateMapping)
-				calculateMappingItem.CreateTime = time.Now()
-				calculateMappingItem.ModifyTime = time.Now()
-				calculateMappingItem.Sort = 1
-				calculateMappingItem.EdbCode = nowEdbInfo.EdbCode
-				calculateMappingItem.EdbInfoId = edbInfoId
-				calculateMappingItem.FromEdbInfoId = secondEdbInfo.EdbInfoId
-				calculateMappingItem.FromEdbCode = secondEdbInfo.EdbCode
-				calculateMappingItem.FromEdbName = secondEdbInfo.EdbName
-				calculateMappingItem.FromSource = secondEdbInfo.Source
-				calculateMappingItem.FromSourceName = secondEdbInfo.SourceName
-				calculateMappingItem.FromTag = "B"
-				calculateMappingItem.Source = nowEdbInfo.Source
-				calculateMappingItem.SourceName = nowEdbInfo.SourceName
-				_, err = to.Insert(calculateMappingItem)
-				if err != nil {
-					return
-				}
-			}
-		} else {
-			if req.Formula != nowEdbInfo.CalculateFormula {
-				//获取第二个指标的数据列表
-				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, secondEdbInfo.SubSource, 0)
-				if tmpErr != nil {
-					return edbInfoId, tmpErr
-				}
-				secondDataList = tmpSecondDataList
-			}
-		}
-
-		//待插入数据
-		for _, v := range secondDataList {
-			//时间戳
-			currentDate, _ := time.Parse(utils.FormatDate, v.DataTime)
-			timestamp := currentDate.UnixNano() / 1e6
-
-			edbDataZjpj := &EdbDataCalculateZjpj{
-				EdbInfoId:     edbInfoId,
-				EdbCode:       nowEdbInfo.EdbCode,
-				DataTime:      v.DataTime,
-				Value:         v.Value,
-				Status:        1,
-				CreateTime:    time.Now(),
-				ModifyTime:    time.Now(),
-				DataTimestamp: timestamp,
-			}
-			addDataList = append(addDataList, edbDataZjpj)
-		}
-	}
-
-	//数据入库
-	tmpAddDataList := make([]*EdbDataCalculateZjpj, 0)
-	for _, v := range addDataList {
-		tmpAddDataList = append(tmpAddDataList, v)
-
-		if len(tmpAddDataList) >= 200 {
-			_, tmpErr := to.InsertMulti(len(tmpAddDataList), tmpAddDataList)
-			if tmpErr != nil {
-				err = tmpErr
-				return
-			}
-			//重新初始化需要加入的数据切片
-			tmpAddDataList = make([]*EdbDataCalculateZjpj, 0)
-		}
-	}
-	//最后如果还有需要新增的数据,那么就统一入库
-	if len(tmpAddDataList) > 0 {
-		_, tmpErr := to.InsertMulti(len(tmpAddDataList), tmpAddDataList)
-		if tmpErr != nil {
-			err = tmpErr
-			return
-		}
-	}
-
-	return
-}

+ 126 - 0
models/data_manage/excel/excel_chart_data.go

@@ -0,0 +1,126 @@
+package excel
+
+import (
+	"eta/eta_mobile/models/data_manage"
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+type ExcelChartData struct {
+	ExcelChartDataId int `orm:"column(excel_chart_data_id);pk"`
+	ExcelInfoId      int `description:"表格id"`
+	ExcelChartEdbId  int `description:"指标ID"`
+	ChartInfoId      int `description:"图表id"`
+	DataTime         string
+	Value            float64
+	ModifyTime       time.Time `description:"修改时间"`
+	CreateTime       time.Time `description:"创建时间"`
+	DataTimestamp    int64
+}
+
+func (e *ExcelChartData) TableName() string {
+	return "excel_chart_data"
+}
+
+// 新增
+func (e *ExcelChartData) Add() (err error) {
+	o := orm.NewOrmUsingDB("data")
+	_, err = o.Insert(e)
+	return
+}
+
+// 修改
+func (e *ExcelChartData) Update(cols []string) (err error) {
+	o := orm.NewOrmUsingDB("data")
+	_, err = o.Update(e, cols...)
+	return
+}
+
+// 删除
+func (e *ExcelChartData) Delete() (err error) {
+	o := orm.NewOrmUsingDB("data")
+	_, err = o.Delete(e)
+	return
+}
+
+// 查询
+func GetExcelChartDataByExcelInfoId(excelInfoId int) (list []*ExcelChartData, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT *
+             FROM excel_chart_data
+			 WHERE excel_info_id=? 
+             ORDER BY excel_chart_edb_id ASC, data_time desc, excel_chart_data_id ASC `
+	_, err = o.Raw(sql, excelInfoId).QueryRows(&list)
+	return
+}
+
+func BatchUpdateChartEdbData(excelInfoId int, excelEdbMap map[int]*ExcelChartEdb, excelDataMap map[int][]*data_manage.EdbDataList) (err error) {
+	o, err := orm.NewOrmUsingDB("data").Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = o.Rollback()
+		} else {
+			_ = o.Commit()
+		}
+	}()
+	//如果有数据则删除所有的数据
+	sql := `delete from excel_chart_data where excel_info_id = ?`
+	_, err = o.Raw(sql, excelInfoId).Exec()
+	if err != nil {
+		return
+	}
+
+	// 图表指标数据入库
+	addList := make([]*ExcelChartData, 0)
+	for chartEdbId, dataList := range excelDataMap {
+		chartEdb, ok := excelEdbMap[chartEdbId]
+		if !ok {
+			err = fmt.Errorf("chartEdbId:%d not exist", chartEdbId)
+			return
+		}
+		for _, v := range dataList {
+			chartData := &ExcelChartData{
+				ExcelInfoId:     chartEdb.ExcelInfoId,
+				ExcelChartEdbId: chartEdb.ExcelChartEdbId,
+				ChartInfoId:     chartEdb.ChartInfoId,
+				DataTime:        v.DataTime,
+				Value:           v.Value,
+				DataTimestamp:   v.DataTimestamp,
+				ModifyTime:      time.Now(),
+				CreateTime:      time.Now(),
+			}
+			addList = append(addList, chartData)
+			// data信息入库
+			if len(addList) > 1000 {
+				_, err = o.InsertMulti(len(addList), addList)
+				if err != nil {
+					return
+				}
+				addList = addList[:0]
+			}
+		}
+	}
+
+	// data信息入库
+	if len(addList) > 0 {
+		_, err = o.InsertMulti(len(addList), addList)
+		if err != nil {
+			return
+		}
+	}
+	return
+}
+
+func GetExcelChartDataByChartInfoId(chartInfoId int) (list []*ExcelChartData, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT *
+             FROM excel_chart_Data
+			 WHERE chart_info_id=? 
+             ORDER BY excel_chart_edb_id ASC `
+	_, err = o.Raw(sql, chartInfoId).QueryRows(&list)
+	return
+}

+ 366 - 0
models/data_manage/excel/excel_chart_edb.go

@@ -0,0 +1,366 @@
+package excel
+
+import (
+	"eta/eta_mobile/models/data_manage"
+	"eta/eta_mobile/utils"
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
+	"strconv"
+	"strings"
+	"time"
+)
+
+type ExcelChartEdb struct {
+	ExcelChartEdbId int       `orm:"column(excel_chart_edb_id);pk"`
+	ExcelInfoId     int       `description:"表格id"`
+	ChartInfoId     int       `description:"图表id"`
+	EdbCode         string    `description:"指标编码"`
+	EdbName         string    `description:"指标名称"`
+	EdbNameEn       string    `description:"指标英文名称"`
+	Unit            string    `description:"指标单位"`
+	UnitEn          string    `description:"指标单位"`
+	DateSequence    string    `description:"日期序列选区"`
+	DataSequence    string    `description:"数据序列选区"`
+	SysUserId       int       `description:"创建人"`
+	SysUserRealName string    `description:"创建人姓名"`
+	MaxData         float64   `description:"上限"`
+	MinData         float64   `description:"下限"`
+	IsOrder         bool      `description:"true:正序,false:逆序"`
+	IsAxis          int       `description:"true:左轴,false:右轴"`
+	EdbInfoType     int       `description:"true:标准指标,false:领先指标"`
+	LeadValue       int       `description:"领先值"`
+	LeadUnit        string    `description:"领先单位"`
+	FromTag         string    `description:"标签"`
+	ModifyTime      time.Time `description:"修改时间"`
+	CreateTime      time.Time `description:"创建时间"`
+	ChartWidth      float64   `description:"线条大小"`
+}
+
+type ExcelChartEdbView struct {
+	ExcelChartEdbId int
+	ExcelInfoId     int    `description:"表格id"`
+	ChartInfoId     int    `description:"图表id"`
+	EdbCode         string `description:"指标编码"`
+	EdbName         string `description:"指标名称"`
+	DateSequenceStr string `description:"日期序列选区"`
+	DataSequenceStr string `description:"数据序列选区"`
+	/*MaxData         float64 `description:"上限"`
+	MinData         float64 `description:"下限"`
+	IsOrder         bool    `description:"true:正序,false:逆序"`
+	IsAxis          int     `description:"true:左轴,false:右轴"`
+	EdbInfoType     int     `description:"true:标准指标,false:领先指标"`
+	LeadValue       int     `description:"领先值"`
+	LeadUnit        string  `description:"领先单位"`*/
+	FromTag string `description:"标签"`
+}
+
+type BalanceTableChart struct {
+	ChartInfoId       int    `description:"图表id,新增时传0"`
+	ChartName         string `description:"图表名称"`
+	ChartType         int    `description:"生成样式:1:曲线图,2:季节性图,3:面积图,4:柱状图,5:散点图,6:组合图,7:柱方图"`
+	Calendar          string `description:"公历/农历"`
+	LeftMin           string `description:"图表左侧最小值"`
+	LeftMax           string `description:"图表左侧最大值"`
+	RightMin          string `description:"图表右侧最小值"`
+	RightMax          string `description:"图表右侧最大值"`
+	Right2Min         string `description:"图表右侧2最小值"`
+	Right2Max         string `description:"图表右侧2最大值"`
+	MinMaxSave        int    `description:"是否手动保存过上下限:0-否;1-是"`
+	ExtraConfig       string `description:"图表额外配置信息,json字符串"`
+	ChartImage        string `description:"封面图" json:"-"`
+	SeasonExtraConfig string `description:"季节性图表中的配置,json数据"`
+	SourcesFrom       string `description:"图表来源"`
+	//	ChartEdbInfoList  []ExcelChartEdbView
+}
+
+func (e *ExcelChartEdb) TableName() string {
+	return "excel_chart_edb"
+}
+
+// 新增
+func (e *ExcelChartEdb) Add() (err error) {
+	o := orm.NewOrmUsingDB("data")
+	_, err = o.Insert(e)
+	return
+}
+
+// 修改
+func (e *ExcelChartEdb) Update(cols []string) (err error) {
+	o := orm.NewOrmUsingDB("data")
+	_, err = o.Update(e, cols...)
+	return
+}
+
+// 删除
+func (e *ExcelChartEdb) Delete() (err error) {
+	o := orm.NewOrmUsingDB("data")
+	_, err = o.Delete(e)
+	return
+}
+
+type AddChartEdbAndDataItem struct {
+	ChartEdb *ExcelChartEdb
+	DataList []*ExcelChartData `description:"数据列表"`
+}
+
+// 同时添加指标和指标数据
+func (e *ExcelChartEdb) AddChartEdbAndData(list []*AddChartEdbAndDataItem, chartInfo *data_manage.ChartInfo, deleteEdbIds []int) (err error) {
+	o, err := orm.NewOrmUsingDB("data").Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = o.Rollback()
+		} else {
+			_ = o.Commit()
+		}
+	}()
+
+	// 先删除原先的绑定的指标
+	if len(deleteEdbIds) > 0 && chartInfo.ChartInfoId > 0 {
+		sql := `DELETE FROM excel_chart_edb WHERE chart_info_id = ? AND excel_chart_edb_id in (` + utils.GetOrmInReplace(len(deleteEdbIds)) + `)`
+		_, err = o.Raw(sql, chartInfo.ChartInfoId, deleteEdbIds).Exec()
+		if err != nil {
+			err = fmt.Errorf("删除原先的指标失败:%v", err)
+			return
+		}
+	}
+	// 图表指标信息入库
+	updateIds := make([]int, 0)
+	var edbInfoIdArrStr []string
+	for _, item := range list {
+		err = addChartEdbAndData(o, item.ChartEdb, item.DataList)
+		if err != nil {
+			return
+		}
+		updateIds = append(updateIds, item.ChartEdb.ExcelChartEdbId)
+		edbInfoIdArrStr = append(edbInfoIdArrStr, strconv.Itoa(item.ChartEdb.ExcelChartEdbId))
+	}
+
+	//新增图表
+	chartInfoId := chartInfo.ChartInfoId
+	if chartInfo.ChartInfoId <= 0 {
+		lastId, e := o.Insert(chartInfo)
+		if e != nil {
+			err = fmt.Errorf("新增图表失败,AddChartEdbAndData: %v", e)
+			return
+		}
+		chartInfoId = int(lastId)
+	} else {
+		_, err = o.Update(chartInfo)
+		if err != nil {
+			err = fmt.Errorf("更新图表失败,AddChartEdbAndData: %v", e)
+			return
+		}
+	}
+
+	//更新图表id
+	sql := `update excel_chart_edb set chart_info_id = ? where excel_chart_edb_id in (` + utils.GetOrmInReplace(len(updateIds)) + `) and chart_info_id=0`
+	_, err = o.Raw(sql, chartInfoId, updateIds).Exec()
+	if err != nil {
+		err = fmt.Errorf("更新图表id失败,AddChartEdbAndData: %v", err)
+		return
+	}
+
+	if len(edbInfoIdArrStr) > 0 {
+		edbInfoIdStr := strings.Join(edbInfoIdArrStr, ",")
+		//更新图表关联的指标id
+		sql = `update chart_info set edb_info_ids = ? where chart_info_id = ?`
+		_, err = o.Raw(sql, edbInfoIdStr, chartInfoId).Exec()
+	}
+	return
+}
+
+func addChartEdbAndData(o orm.TxOrmer, chartEdb *ExcelChartEdb, dataList []*ExcelChartData) (err error) {
+	// 图表指标信息入库
+	excelChartEdbId := chartEdb.ExcelChartEdbId
+	if chartEdb.ExcelChartEdbId <= 0 {
+		lastId, e := o.Insert(chartEdb)
+		if e != nil {
+			err = fmt.Errorf("新增指标失败,addChartEdbAndData: %v", e)
+			return
+		}
+		excelChartEdbId = int(lastId)
+	} else {
+		_, e := o.Update(chartEdb)
+		if e != nil {
+			err = fmt.Errorf("更新指标失败,addChartEdbAndData: %v", e)
+			return
+		}
+		//如果有数据则删除所有的数据
+		sql := `delete from excel_chart_data where excel_chart_edb_id = ?`
+		_, err = o.Raw(sql, excelChartEdbId).Exec()
+		if err != nil {
+			return
+		}
+	}
+
+	chartEdb.ExcelChartEdbId = excelChartEdbId
+
+	// 图表指标数据入库
+	addList := make([]*ExcelChartData, 0)
+	if len(dataList) > 0 {
+		for _, v := range dataList {
+			chartData := &ExcelChartData{
+				ExcelInfoId:     chartEdb.ExcelInfoId,
+				ExcelChartEdbId: chartEdb.ExcelChartEdbId,
+				ChartInfoId:     chartEdb.ChartInfoId,
+				DataTime:        v.DataTime,
+				Value:           v.Value,
+				DataTimestamp:   v.DataTimestamp,
+				ModifyTime:      time.Now(),
+				CreateTime:      time.Now(),
+			}
+			addList = append(addList, chartData)
+			// data信息入库
+			if len(addList) > 1000 {
+				_, err = o.InsertMulti(len(addList), addList)
+				if err != nil {
+					return
+				}
+				addList = addList[:0]
+			}
+		}
+	}
+
+	// data信息入库
+	if len(addList) > 0 {
+		_, err = o.InsertMulti(len(addList), addList)
+		if err != nil {
+			return
+		}
+	}
+	return
+}
+
+func GetExcelChartEdbMappingByExcelInfoId(excelInfoId int) (list []*ExcelChartEdb, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT *
+             FROM excel_chart_edb 
+			 WHERE excel_info_id=? 
+             ORDER BY chart_info_id asc, excel_chart_edb_id ASC `
+	_, err = o.Raw(sql, excelInfoId).QueryRows(&list)
+	return
+}
+
+func GetExcelChartEdbMappingByExcelInfoIds(excelInfoIds []int) (list []*ExcelChartEdb, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT *
+             FROM excel_chart_edb 
+			 WHERE excel_info_id in (` + utils.GetOrmInReplace(len(excelInfoIds)) + `)`
+	_, err = o.Raw(sql, excelInfoIds).QueryRows(&list)
+	return
+}
+
+func GetExcelChartEdbById(id int) (item *ExcelChartEdb, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT * FROM excel_chart_edb WHERE excel_chart_edb_id=? `
+	err = o.Raw(sql, id).QueryRow(&item)
+	return
+}
+
+func GetExcelChartEdbMappingByChartInfoId(chartInfoId int) (list []*ExcelChartEdb, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT *
+             FROM excel_chart_edb 
+			 WHERE chart_info_id=? 
+             ORDER BY excel_chart_edb_id ASC `
+	_, err = o.Raw(sql, chartInfoId).QueryRows(&list)
+	return
+}
+
+func GetExcelInfoByChartInfoId(chartInfoId int) (item *ExcelInfo, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT i.*
+             FROM excel_chart_edb e left join excel_info i on e.excel_info_id=i.excel_info_id
+			 WHERE e.chart_info_id=? limit 1`
+	err = o.Raw(sql, chartInfoId).QueryRow(&item)
+	return
+}
+
+// 同时删除指标和指标数据
+func DeleteExcelChartEdbAndData(excelInfoIds []int, chartInfoIds []int) (err error) {
+	o, err := orm.NewOrmUsingDB("data").Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = o.Rollback()
+		} else {
+			_ = o.Commit()
+		}
+	}()
+	// 把对应的表格状态改成删除状态
+	//更新图表id
+	sql := `update excel_info set is_delete = 1, modify_time = ? where excel_info_id in (` + utils.GetOrmInReplace(len(excelInfoIds)) + `)`
+	_, err = o.Raw(sql, time.Now(), excelInfoIds).Exec()
+	if err != nil {
+		err = fmt.Errorf("更新图表id失败,AddChartEdbAndData: %v", err)
+		return
+	}
+	// 把删除图表状态
+	if len(chartInfoIds) > 0 {
+		sql := `DELETE FROM chart_info WHERE  chart_info_id in (` + utils.GetOrmInReplace(len(chartInfoIds)) + `)`
+		_, err = o.Raw(sql, chartInfoIds).Exec()
+		if err != nil {
+			err = fmt.Errorf("删除原先的指标失败:%v", err)
+			return
+		}
+
+		// todo 如果加入到我的图库中,则删除我的图库中的数据
+	}
+	// 删除原先的绑定的指标
+	sql = `DELETE FROM excel_chart_edb WHERE  excel_info_id in (` + utils.GetOrmInReplace(len(excelInfoIds)) + `)`
+	_, err = o.Raw(sql, excelInfoIds).Exec()
+	if err != nil {
+		err = fmt.Errorf("删除原先的指标失败:%v", err)
+		return
+	}
+	// 删除指标数据
+	sql = `DELETE FROM excel_chart_data WHERE  excel_info_id in (` + utils.GetOrmInReplace(len(excelInfoIds)) + `)`
+	_, err = o.Raw(sql, excelInfoIds).Exec()
+	if err != nil {
+		err = fmt.Errorf("删除原先的指标失败:%v", err)
+		return
+	}
+	return
+}
+
+// 删除平衡表中的指标和数据
+func DeleteBalanceExcelChartInfoAndData(chartInfoId 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()
+		}
+	}()
+
+	sql := ` DELETE FROM chart_info WHERE chart_info_id=? `
+	_, err = to.Raw(sql, chartInfoId).Exec()
+	if err != nil {
+		err = fmt.Errorf("删除平衡表图表失败 %s", err.Error())
+		return
+	}
+	sql = ` DELETE FROM  excel_chart_edb WHERE chart_info_id=? `
+	_, err = to.Raw(sql, chartInfoId).Exec()
+	if err != nil {
+		err = fmt.Errorf("删除平衡表图表指标失败 %s", err.Error())
+		return
+	}
+	// 删除表格里的数据
+	sql = ` DELETE FROM  excel_chart_data WHERE chart_info_id=? `
+	_, err = to.Raw(sql, chartInfoId).Exec()
+	if err != nil {
+		err = fmt.Errorf("删除平衡表图表指标失败 %s", err.Error())
+		return
+	}
+	return
+}

+ 46 - 16
models/data_manage/excel/excel_info.go

@@ -9,22 +9,29 @@ import (
 
 // ExcelInfo excel表格详情表
 type ExcelInfo struct {
-	ExcelInfoId      int       `orm:"column(excel_info_id);pk"`
-	Source           int       `description:"表格来源,1:excel插件的表格,2:自定义表格,3:混合表格,4:自定义分析,默认:1"`
-	ExcelType        int       `description:"表格类型,1:指标列,2:日期列,默认:1"`
-	ExcelName        string    `description:"表格名称"`
-	UniqueCode       string    `description:"表格唯一编码"`
-	ExcelClassifyId  int       `description:"表格分类id"`
-	SysUserId        int       `description:"操作人id"`
-	SysUserRealName  string    `description:"操作人真实姓名"`
-	Content          string    `description:"表格内容"`
-	ExcelImage       string    `description:"表格图片"`
-	FileUrl          string    `description:"表格下载地址"`
-	Sort             int       `description:"排序字段,数字越小越排前面"`
-	IsDelete         int       `description:"是否删除,0:未删除,1:已删除"`
-	ModifyTime       time.Time `description:"最近修改日期"`
-	CreateTime       time.Time `description:"创建日期"`
-	IsJoinPermission int       `description:"是否加入权限管控,0:不加入;1:加入;默认:0"`
+	ExcelInfoId        int       `orm:"column(excel_info_id);pk"`
+	Source             int       `description:"表格来源,1:excel插件的表格,2:自定义表格,3:混合表格,4:自定义分析,默认:1"`
+	ExcelType          int       `description:"表格类型,1:指标列,2:日期列,默认:1"`
+	ExcelName          string    `description:"表格名称"`
+	UniqueCode         string    `description:"表格唯一编码"`
+	ExcelClassifyId    int       `description:"表格分类id"`
+	SysUserId          int       `description:"操作人id"`
+	SysUserRealName    string    `description:"操作人真实姓名"`
+	Content            string    `description:"表格内容"`
+	ExcelImage         string    `description:"表格图片"`
+	FileUrl            string    `description:"表格下载地址"`
+	Sort               int       `description:"排序字段,数字越小越排前面"`
+	IsDelete           int       `description:"是否删除,0:未删除,1:已删除"`
+	ModifyTime         time.Time `description:"最近修改日期"`
+	CreateTime         time.Time `description:"创建日期"`
+	IsJoinPermission   int       `description:"是否加入权限管控,0:不加入;1:加入;默认:0"`
+	ParentId           int       `description:"表格的父级id"`
+	BalanceType        int       `description:"平衡表类型:0 动态表,1静态表"`
+	UpdateUserId       int       `description:"更新人id"`
+	UpdateUserRealName string    `description:"更新人真实姓名"`
+	RelExcelInfoId     int       `description:"平衡表里静态表关联的动态表excel id"`
+	VersionName        string    `description:"静态表版本名称"`
+	SourcesFrom        string    `description:"图表来源"`
 }
 
 // Update 更新 excel表格基础信息
@@ -261,6 +268,17 @@ func GetExcelInfoByUniqueCode(uniqueCode string) (item *ExcelInfo, err error) {
 	return
 }
 
+func GetExcelInfoListByCondition(condition string, pars []interface{}) (items []*ExcelInfo, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT * FROM excel_info WHERE 1=1 AND is_delete=0 `
+	if condition != "" {
+		sql += condition
+	}
+	sql += ` ORDER BY sort asc, excel_info_id asc`
+	_, err = o.Raw(sql, pars).QueryRows(&items)
+	return
+}
+
 // GetFirstExcelInfoByClassifyId 获取当前分类下,且排序数相同 的排序第一条的数据
 func GetFirstExcelInfoByClassifyId(classifyId int) (item *ExcelInfo, err error) {
 	o := orm.NewOrmUsingDB("data")
@@ -623,3 +641,15 @@ func ModifyExcelInfoUserIdByOldUserId(oldUserIdList []int, userId int, userName
 	_, err = o.Raw(sql, userId, userName, oldUserIdList).Exec()
 	return
 }
+
+// ExcelInfoDetailButton 操作按钮
+type ExcelInfoDetailButton struct {
+	RefreshButton    bool `description:"是否可刷新"`
+	CopyButton       bool `description:"是否可另存为"`
+	DownloadButton   bool `description:"是否可下载"`
+	OpButton         bool `description:"是否可编辑"`
+	DeleteButton     bool `description:"是否可删除"`
+	OpEdbButton      bool `description:"是否可生成指标"`
+	RefreshEdbButton bool `description:"是否可刷新指标"`
+	OpWorkerButton   bool `description:"是否修改协作人"`
+}

+ 82 - 0
models/data_manage/excel/excel_worker.go

@@ -0,0 +1,82 @@
+package excel
+
+import (
+	"eta/eta_mobile/utils"
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+type ExcelWorker struct {
+	ExcelWorkerId   int       `orm:"column(excel_worker_id);pk"`
+	ExcelInfoId     int       `description:"表格id"`
+	SysUserId       int       `description:"创建人"`
+	SysUserRealName string    `description:"创建人姓名"`
+	ModifyTime      time.Time `description:"修改时间"`
+	CreateTime      time.Time `description:"创建时间"`
+}
+
+func (e *ExcelWorker) TableName() string {
+	return "excel_worker"
+}
+
+// 新增 协作人
+func (e *ExcelWorker) AddWorker(excelInfoId int, addWorkers []*ExcelWorker, notDeleteWorkers []string) (err error) {
+	o, err := orm.NewOrmUsingDB("data").Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = o.Rollback()
+		} else {
+			_ = o.Commit()
+		}
+	}()
+	if len(notDeleteWorkers) > 0 {
+		sql := `delete from excel_worker where excel_info_id = ? and sys_user_id not in (` + utils.GetOrmInReplace(len(notDeleteWorkers)) + `)`
+		_, err = o.Raw(sql, excelInfoId, notDeleteWorkers).Exec()
+		if err != nil {
+			return
+		}
+	} else if len(notDeleteWorkers) == 0 { // 清空协作人
+		sql := `delete from excel_worker where excel_info_id = ? `
+		_, err = o.Raw(sql, excelInfoId).Exec()
+		if err != nil {
+			return
+		}
+	}
+	if len(addWorkers) > 0 {
+		_, err = o.InsertMulti(len(addWorkers), addWorkers)
+	}
+	return
+}
+
+// 修改
+func (e *ExcelWorker) Update(cols []string) (err error) {
+	o := orm.NewOrmUsingDB("data")
+	_, err = o.Update(e, cols...)
+	return
+}
+
+// 删除
+func (e *ExcelWorker) Delete() (err error) {
+	o := orm.NewOrmUsingDB("data")
+	_, err = o.Delete(e)
+	return
+}
+
+// 查询
+func (e *ExcelWorker) GetByExcelInfoId(excelInfoId int) (items []*ExcelWorker, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `select * from excel_worker where excel_info_id = ? `
+	_, err = o.Raw(sql, excelInfoId).QueryRows(&items)
+	return
+}
+
+// 查询
+func (e *ExcelWorker) GetBySysUserId(sysUserId int) (items []*ExcelWorker, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `select * from excel_worker where sys_user_id = ? `
+	_, err = o.Raw(sql, sysUserId).QueryRows(&items)
+	return
+}

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

@@ -23,6 +23,7 @@ type AddExcelInfoReq struct {
 	ExcelClassifyId int         `description:"分类id"`
 	Content         string      `description:"Excel表格内容"`
 	TableData       interface{} `description:"自定义表格的数据内容"`
+	SourcesFrom     string      `description:"图表来源"`
 }
 
 // EditExcelInfoReq 编辑表格请求
@@ -34,6 +35,7 @@ type EditExcelInfoReq struct {
 	ExcelClassifyId int         `description:"分类id"`
 	Content         string      `description:"Excel表格内容"`
 	TableData       interface{} `description:"自定义表格的数据内容"`
+	SourcesFrom     string      `description:"图表来源"`
 }
 
 // SetExcelInfoImageReq 设置excel表格图片请求

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

@@ -45,6 +45,16 @@ type MixedTableCellDataReq struct {
 	Extra           string      `description:"额外参数"`
 	ShowStyle       string      `description:"展示的样式配置"`
 	ShowFormatValue interface{} `description:"样式处理后的值"`
+	MerData         *struct {
+		Type string `json:"type"`
+		Mer  struct {
+			SKey    string `json:"sKey"`
+			Rowspan int    `json:"rowspan"`
+			Colspan int    `json:"colspan"`
+			Row     int    `json:"row"`
+			Col     int    `json:"col"`
+		} `json:"mer"`
+	} `json:"merData" description:"合并单元格"`
 }
 
 // CellRelationConf

+ 41 - 28
models/data_manage/excel/response/excel_info.go

@@ -22,11 +22,14 @@ type ExcelListResp struct {
 
 // ExcelTableDetailResp  excel表格详情
 type ExcelTableDetailResp struct {
-	UniqueCode string `description:"表格唯一code"`
-	ExcelImage string `description:"表格截图"`
-	ExcelName  string `description:"表格名称"`
-	TableInfo  excel.TableData
-	Config     ExcelTableDetailConfigResp
+	UniqueCode    string `description:"表格唯一code"`
+	ExcelImage    string `description:"表格截图"`
+	ExcelName     string `description:"表格名称"`
+	TableInfo     excel.TableData
+	Config        ExcelTableDetailConfigResp
+	SourcesFrom   string `description:"图表来源"`
+	ExcelSource   string `description:"表格来源str"`
+	ExcelSourceEn string `description:"表格来源(英文)"`
 }
 
 // ExcelTableDetailConfigResp
@@ -44,8 +47,10 @@ type TableCellResp struct {
 }
 
 type TableDataItem struct {
-	EdbInfoId int                     `description:"指标id"`
-	Data      []request.ManualDataReq `description:"数据列表"`
+	EdbInfoId     int                     `description:"指标id"`
+	Data          []request.ManualDataReq `description:"数据列表"`
+	ExcelSource   string                  `description:"表格来源str"`
+	ExcelSourceEn string                  `description:"表格来源(英文)"`
 }
 
 // TableDetailResp  excel表格详情
@@ -56,27 +61,35 @@ type TableDetailResp struct {
 
 // ExcelInfoDetail excel表格详情(前端使用)
 type ExcelInfoDetail struct {
-	ExcelInfoId      int                   `orm:"column(excel_info_id);pk"`
-	Source           int                   `description:"表格来源,1:excel插件的表格,2:自定义表格,默认:1"`
-	ExcelType        int                   `description:"表格类型,1:指标列,2:日期列,默认:1"`
-	ExcelName        string                `description:"表格名称"`
-	UniqueCode       string                `description:"表格唯一编码"`
-	ExcelClassifyId  int                   `description:"表格分类id"`
-	SysUserId        int                   `description:"操作人id"`
-	SysUserRealName  string                `description:"操作人真实姓名"`
-	Content          string                `description:"表格内容"`
-	ExcelImage       string                `description:"表格图片"`
-	FileUrl          string                `description:"表格下载地址"`
-	Sort             int                   `description:"排序字段,数字越小越排前面"`
-	IsDelete         int                   `description:"是否删除,0:未删除,1:已删除"`
-	ModifyTime       time.Time             `description:"最近修改日期"`
-	CreateTime       time.Time             `description:"创建日期"`
-	TableData        interface{}           `description:"表格内容"`
-	Button           ExcelInfoDetailButton `description:"操作权限"`
-	CanEdit          bool                  `description:"是否可编辑"`
-	Editor           string                `description:"编辑人"`
-	IsJoinPermission int                   `description:"是否加入权限管控,0:不加入;1:加入;默认:0"`
-	HaveOperaAuth    bool                  `description:"是否有数据权限"`
+	ExcelInfoId        int                          `orm:"column(excel_info_id);pk"`
+	Source             int                          `description:"表格来源,1:excel插件的表格,2:自定义表格,默认:1"`
+	ExcelType          int                          `description:"表格类型,1:指标列,2:日期列,默认:1"`
+	ExcelName          string                       `description:"表格名称"`
+	UniqueCode         string                       `description:"表格唯一编码"`
+	ExcelClassifyId    int                          `description:"表格分类id"`
+	SysUserId          int                          `description:"操作人id"`
+	SysUserRealName    string                       `description:"操作人真实姓名"`
+	Content            string                       `description:"表格内容"`
+	ExcelImage         string                       `description:"表格图片"`
+	FileUrl            string                       `description:"表格下载地址"`
+	Sort               int                          `description:"排序字段,数字越小越排前面"`
+	IsDelete           int                          `description:"是否删除,0:未删除,1:已删除"`
+	ModifyTime         time.Time                    `description:"最近修改日期"`
+	CreateTime         time.Time                    `description:"创建日期"`
+	TableData          interface{}                  `description:"表格内容"`
+	Button             excel2.ExcelInfoDetailButton `description:"操作权限"`
+	CanEdit            bool                         `description:"是否可编辑"`
+	Editor             string                       `description:"编辑人"`
+	IsJoinPermission   int                          `description:"是否加入权限管控,0:不加入;1:加入;默认:0"`
+	HaveOperaAuth      bool                         `description:"是否有数据权限"`
+	ParentId           int                          `description:"表格的父级id"`
+	BalanceType        int                          `description:"平衡表类型:0 动态表,1静态表"`
+	UpdateUserId       int                          `description:"更新人id"`
+	UpdateUserRealName string                       `description:"更新人真实姓名"`
+	RelExcelInfoId     int                          `description:"平衡表里静态表关联的动态表excel id"`
+	SourcesFrom        string                       `description:"图表来源"`
+	ExcelSource        string                       `description:"表格来源str"`
+	ExcelSourceEn      string                       `description:"表格来源(英文)"`
 }
 
 // ExcelInfoDetailButton 操作按钮

+ 17 - 17
models/data_manage/excel/response/sheet.go

@@ -14,21 +14,21 @@ type FindExcelInfoResp struct {
 
 // FindExcelInfo excel的数据详情
 type FindExcelInfo struct {
-	ExcelInfoId     int                   `orm:"column(excel_info_id);pk"`
-	Source          int                   `description:"表格来源,1:excel插件的表格,2:自定义表格,默认:1"`
-	ExcelType       int                   `description:"表格类型,1:指标列,2:日期列,默认:1"`
-	ExcelName       string                `description:"表格名称"`
-	UniqueCode      string                `description:"表格唯一编码"`
-	ExcelClassifyId int                   `description:"表格分类id"`
-	SysUserId       int                   `description:"操作人id"`
-	SysUserRealName string                `description:"操作人真实姓名"`
-	ExcelImage      string                `description:"表格图片"`
-	FileUrl         string                `description:"表格下载地址"`
-	Sort            int                   `description:"排序字段,数字越小越排前面"`
-	ModifyTime      time.Time             `description:"最近修改日期"`
-	CreateTime      time.Time             `description:"创建日期"`
-	Button          ExcelInfoDetailButton `description:"操作权限"`
-	CanEdit         bool                  `description:"是否可编辑"`
-	Editor          string                `description:"编辑人"`
-	HaveOperaAuth   bool                  `description:"是否有数据权限,默认:false"`
+	ExcelInfoId     int                         `orm:"column(excel_info_id);pk"`
+	Source          int                         `description:"表格来源,1:excel插件的表格,2:自定义表格,默认:1"`
+	ExcelType       int                         `description:"表格类型,1:指标列,2:日期列,默认:1"`
+	ExcelName       string                      `description:"表格名称"`
+	UniqueCode      string                      `description:"表格唯一编码"`
+	ExcelClassifyId int                         `description:"表格分类id"`
+	SysUserId       int                         `description:"操作人id"`
+	SysUserRealName string                      `description:"操作人真实姓名"`
+	ExcelImage      string                      `description:"表格图片"`
+	FileUrl         string                      `description:"表格下载地址"`
+	Sort            int                         `description:"排序字段,数字越小越排前面"`
+	ModifyTime      time.Time                   `description:"最近修改日期"`
+	CreateTime      time.Time                   `description:"创建日期"`
+	Button          excel.ExcelInfoDetailButton `description:"操作权限"`
+	CanEdit         bool                        `description:"是否可编辑"`
+	Editor          string                      `description:"编辑人"`
+	HaveOperaAuth   bool                        `description:"是否有数据权限,默认:false"`
 }

+ 350 - 0
models/data_manage/factor_edb_series.go

@@ -0,0 +1,350 @@
+package data_manage
+
+import (
+	"encoding/json"
+	"eta/eta_mobile/utils"
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
+	"strings"
+	"time"
+)
+
+const (
+	FactorEdbSeriesCalculateNone = 0
+	FactorEdbSeriesCalculating   = 1
+	FactorEdbSeriesCalculated    = 2
+)
+
+// FactorEdbSeries 因子指标系列表
+type FactorEdbSeries struct {
+	FactorEdbSeriesId int       `orm:"column(factor_edb_series_id);pk"`
+	SeriesName        string    `description:"系列名称"`
+	EdbInfoType       int       `description:"关联指标类型:0-普通指标;1-预测指标"`
+	CalculateStep     string    `description:"计算步骤-JSON"`
+	CalculateState    int       `description:"计算状态: 0-无计算; 1-计算中; 2-计算完成"`
+	CreateTime        time.Time `description:"创建时间"`
+	ModifyTime        time.Time `description:"修改时间"`
+}
+
+func (m *FactorEdbSeries) TableName() string {
+	return "factor_edb_series"
+}
+
+type FactorEdbSeriesCols struct {
+	PrimaryId      string
+	SeriesName     string
+	EdbInfoType    string
+	CalculateStep  string
+	CalculateState string
+	CreateTime     string
+	ModifyTime     string
+}
+
+func (m *FactorEdbSeries) Cols() FactorEdbSeriesCols {
+	return FactorEdbSeriesCols{
+		PrimaryId:      "factor_edb_series_id",
+		SeriesName:     "series_name",
+		EdbInfoType:    "edb_info_type",
+		CalculateStep:  "calculate_step",
+		CalculateState: "calculate_state",
+		CreateTime:     "create_time",
+		ModifyTime:     "modify_time",
+	}
+}
+
+func (m *FactorEdbSeries) Create() (err error) {
+	o := orm.NewOrmUsingDB("data")
+	id, err := o.Insert(m)
+	if err != nil {
+		return
+	}
+	m.FactorEdbSeriesId = int(id)
+	return
+}
+
+func (m *FactorEdbSeries) CreateMulti(items []*FactorEdbSeries) (err error) {
+	if len(items) == 0 {
+		return
+	}
+	o := orm.NewOrmUsingDB("data")
+	_, err = o.InsertMulti(len(items), items)
+	return
+}
+
+func (m *FactorEdbSeries) Update(cols []string) (err error) {
+	o := orm.NewOrmUsingDB("data")
+	_, err = o.Update(m, cols...)
+	return
+}
+
+func (m *FactorEdbSeries) Remove() (err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.Cols().PrimaryId)
+	_, err = o.Raw(sql, m.FactorEdbSeriesId).Exec()
+	return
+}
+
+func (m *FactorEdbSeries) MultiRemove(ids []int) (err error) {
+	if len(ids) == 0 {
+		return
+	}
+	o := orm.NewOrmUsingDB("data")
+	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s IN (%s)`, m.TableName(), m.Cols().PrimaryId, utils.GetOrmInReplace(len(ids)))
+	_, err = o.Raw(sql, ids).Exec()
+	return
+}
+
+func (m *FactorEdbSeries) GetItemById(id int) (item *FactorEdbSeries, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.Cols().PrimaryId)
+	err = o.Raw(sql, id).QueryRow(&item)
+	return
+}
+
+func (m *FactorEdbSeries) GetItemByCondition(condition string, pars []interface{}, orderRule string) (item *FactorEdbSeries, err error) {
+	o := orm.NewOrmUsingDB("data")
+	order := ``
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE 1=1 %s %s LIMIT 1`, m.TableName(), condition, order)
+	err = o.Raw(sql, pars).QueryRow(&item)
+	return
+}
+
+func (m *FactorEdbSeries) GetCountByCondition(condition string, pars []interface{}) (count int, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := fmt.Sprintf(`SELECT COUNT(1) FROM %s WHERE 1=1 %s`, m.TableName(), condition)
+	err = o.Raw(sql, pars).QueryRow(&count)
+	return
+}
+
+func (m *FactorEdbSeries) GetItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string) (items []*FactorEdbSeries, err error) {
+	o := orm.NewOrmUsingDB("data")
+	fields := strings.Join(fieldArr, ",")
+	if len(fieldArr) == 0 {
+		fields = `*`
+	}
+	order := fmt.Sprintf(`ORDER BY %s DESC`, m.Cols().CreateTime)
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT %s FROM %s WHERE 1=1 %s %s`, fields, m.TableName(), condition, order)
+	_, err = o.Raw(sql, pars).QueryRows(&items)
+	return
+}
+
+func (m *FactorEdbSeries) GetPageItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string, startSize, pageSize int) (items []*FactorEdbSeries, err error) {
+	o := orm.NewOrmUsingDB("data")
+	fields := strings.Join(fieldArr, ",")
+	if len(fieldArr) == 0 {
+		fields = `*`
+	}
+	order := fmt.Sprintf(`ORDER BY %s DESC`, m.Cols().CreateTime)
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT %s FROM %s WHERE 1=1 %s %s LIMIT ?,?`, fields, m.TableName(), condition, order)
+	_, err = o.Raw(sql, pars, startSize, pageSize).QueryRows(&items)
+	return
+}
+
+// FactorEdbSeriesItem 多因子系列信息
+type FactorEdbSeriesItem struct {
+	SeriesId      int                            `description:"多因子系列ID"`
+	SeriesName    string                         `description:"系列名称"`
+	EdbInfoType   int                            `description:"关联指标类型:0-普通指标;1-预测指标"`
+	CalculateStep []FactorEdbSeriesCalculatePars `description:"计算步骤-JSON"`
+	CreateTime    string                         `description:"创建时间"`
+	ModifyTime    string                         `description:"修改时间"`
+}
+
+func (m *FactorEdbSeries) Format2Item() (item *FactorEdbSeriesItem) {
+	item = new(FactorEdbSeriesItem)
+	item.SeriesId = m.FactorEdbSeriesId
+	item.SeriesName = m.SeriesName
+	item.EdbInfoType = m.EdbInfoType
+	if m.CalculateStep != "" {
+		_ = json.Unmarshal([]byte(m.CalculateStep), &item.CalculateStep)
+	}
+	item.CreateTime = utils.TimeTransferString(utils.FormatDateTime, m.CreateTime)
+	item.ModifyTime = utils.TimeTransferString(utils.FormatDateTime, m.ModifyTime)
+	return
+}
+
+// FactorEdbSeriesCalculatePars 计算参数
+type FactorEdbSeriesCalculatePars struct {
+	Formula       interface{} `description:"N值/移动天数/指数修匀alpha值/计算公式等"`
+	Calendar      string      `description:"公历/农历"`
+	Frequency     string      `description:"需要转换的频度"`
+	MoveType      int         `description:"移动方式: 1-领先(默认); 2-滞后"`
+	MoveFrequency string      `description:"移动频度"`
+	FromFrequency string      `description:"来源的频度"`
+	Source        int         `description:"计算方式来源(不是指标来源)"`
+	Sort          int         `description:"计算顺序"`
+}
+
+// CreateSeriesAndMapping 新增系列和指标关联
+func (m *FactorEdbSeries) CreateSeriesAndMapping(item *FactorEdbSeries, mappings []*FactorEdbSeriesMapping) (seriesId int, err error) {
+	if item == nil {
+		err = fmt.Errorf("series is nil")
+		return
+	}
+	o := orm.NewOrmUsingDB("data")
+	tx, e := o.Begin()
+	if e != nil {
+		err = fmt.Errorf("orm begin err: %v", e)
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = tx.Rollback()
+			return
+		}
+		_ = tx.Commit()
+	}()
+
+	id, e := tx.Insert(item)
+	if e != nil {
+		err = fmt.Errorf("insert series err: %v", e)
+		return
+	}
+	seriesId = int(id)
+	item.FactorEdbSeriesId = seriesId
+
+	if len(mappings) > 0 {
+		for _, v := range mappings {
+			v.FactorEdbSeriesId = seriesId
+		}
+		_, e = tx.InsertMulti(200, mappings)
+		if e != nil {
+			err = fmt.Errorf("insert multi mapping err: %v", e)
+			return
+		}
+	}
+	return
+}
+
+// EditSeriesAndMapping 编辑系列和指标关联
+func (m *FactorEdbSeries) EditSeriesAndMapping(item *FactorEdbSeries, mappings []*FactorEdbSeriesMapping, updateCols []string) (err error) {
+	if item == nil {
+		err = fmt.Errorf("series is nil")
+		return
+	}
+	o := orm.NewOrmUsingDB("data")
+	tx, e := o.Begin()
+	if e != nil {
+		err = fmt.Errorf("orm begin err: %v", e)
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = tx.Rollback()
+			return
+		}
+		_ = tx.Commit()
+	}()
+
+	_, e = tx.Update(item, updateCols...)
+	if e != nil {
+		err = fmt.Errorf("update series err: %v", e)
+		return
+	}
+
+	// 清除原指标关联
+	mappingOb := new(FactorEdbSeriesMapping)
+	cond := fmt.Sprintf("%s = ?", mappingOb.Cols().FactorEdbSeriesId)
+	pars := make([]interface{}, 0)
+	pars = append(pars, item.FactorEdbSeriesId)
+	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s`, mappingOb.TableName(), cond)
+	_, e = tx.Raw(sql, pars).Exec()
+	if e != nil {
+		err = fmt.Errorf("remove mapping err: %v", e)
+		return
+	}
+
+	if len(mappings) > 0 {
+		for _, v := range mappings {
+			v.FactorEdbSeriesId = item.FactorEdbSeriesId
+		}
+		_, e = tx.InsertMulti(200, mappings)
+		if e != nil {
+			err = fmt.Errorf("insert multi mapping err: %v", e)
+			return
+		}
+	}
+	return
+}
+
+// FactorEdbSeriesStepCalculateResp 批量计算响应
+type FactorEdbSeriesStepCalculateResp struct {
+	SeriesId int                                  `description:"多因子指标系列ID"`
+	Fail     []FactorEdbSeriesStepCalculateResult `description:"计算失败的指标"`
+	Success  []FactorEdbSeriesStepCalculateResult `description:"计算成功的指标"`
+}
+
+// FactorEdbSeriesStepCalculateResult 批量计算结果
+type FactorEdbSeriesStepCalculateResult struct {
+	EdbInfoId int    `description:"指标ID"`
+	EdbCode   string `description:"指标编码"`
+	Msg       string `description:"提示信息"`
+	ErrMsg    string `description:"错误信息"`
+}
+
+// FactorEdbSeriesDetail 因子指标系列-详情
+type FactorEdbSeriesDetail struct {
+	*FactorEdbSeriesItem
+	EdbMappings []*FactorEdbSeriesMappingItem
+}
+
+// FactorEdbSeriesCorrelationMatrixResp 因子指标系列-相关性矩阵响应
+type FactorEdbSeriesCorrelationMatrixResp struct {
+	Fail    []FactorEdbSeriesCorrelationMatrixItem `description:"计算失败的指标"`
+	Success []FactorEdbSeriesCorrelationMatrixItem `description:"计算成功的指标"`
+}
+
+// FactorEdbSeriesCorrelationMatrixItem 因子指标系列-相关性矩阵信息
+type FactorEdbSeriesCorrelationMatrixItem struct {
+	SeriesId   int                                      `description:"因子指标系列ID"`
+	EdbInfoId  int                                      `description:"指标ID"`
+	EdbCode    string                                   `description:"指标编码"`
+	EdbName    string                                   `description:"指标名称"`
+	Values     []FactorEdbSeriesCorrelationMatrixValues `description:"X轴和Y轴数据"`
+	Msg        string                                   `description:"提示信息"`
+	ErrMsg     string                                   `description:"错误信息"`
+	Used       bool                                     `description:"是否选中"`
+	SourceName string                                   `description:"指标来源名称"`
+}
+
+// FactorEdbSeriesCorrelationMatrixValues 因子指标系列-相关性矩阵XY值
+type FactorEdbSeriesCorrelationMatrixValues struct {
+	XData int     `description:"X轴数据"`
+	YData float64 `description:"Y轴数据"`
+}
+
+// FactorEdbSeriesCorrelationMatrixOrder 排序规则[0 1 2 3 -1 -2 -3]
+type FactorEdbSeriesCorrelationMatrixOrder []FactorEdbSeriesCorrelationMatrixValues
+
+func (a FactorEdbSeriesCorrelationMatrixOrder) Len() int {
+	return len(a)
+}
+
+func (a FactorEdbSeriesCorrelationMatrixOrder) Swap(i, j int) {
+	a[i], a[j] = a[j], a[i]
+}
+
+func (a FactorEdbSeriesCorrelationMatrixOrder) Less(i, j int) bool {
+	// 非负数优先
+	if a[i].XData >= 0 && a[j].XData < 0 {
+		return true
+	}
+	if a[i].XData < 0 && a[j].XData >= 0 {
+		return false
+	}
+	// 非负数升序排序
+	if a[i].XData >= 0 {
+		return a[i].XData < a[j].XData
+	}
+	// 负数按绝对值的降序排序(即数值的升序)
+	return a[i].XData > a[j].XData
+}

+ 190 - 0
models/data_manage/factor_edb_series_calculate_data.go

@@ -0,0 +1,190 @@
+package data_manage
+
+import (
+	"eta/eta_mobile/utils"
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
+	"strings"
+	"time"
+)
+
+// FactorEdbSeriesCalculateData 因子指标系列-指标计算数据表
+type FactorEdbSeriesCalculateData struct {
+	FactorEdbSeriesCalculateDataId int       `orm:"column(factor_edb_series_calculate_data_id);pk"`
+	FactorEdbSeriesId              int       `description:"因子指标系列ID"`
+	EdbInfoId                      int       `description:"指标ID"`
+	EdbCode                        string    `description:"指标编码"`
+	DataTime                       time.Time `description:"数据日期"`
+	Value                          float64   `description:"数据值"`
+	CreateTime                     time.Time `description:"创建时间"`
+	ModifyTime                     time.Time `description:"修改时间"`
+	DataTimestamp                  int64     `description:"数据日期时间戳"`
+}
+
+func (m *FactorEdbSeriesCalculateData) TableName() string {
+	return "factor_edb_series_calculate_data"
+}
+
+type FactorEdbSeriesCalculateDataCols struct {
+	PrimaryId         string
+	FactorEdbSeriesId string
+	EdbInfoId         string
+	EdbCode           string
+	DataTime          string
+	Value             string
+	CreateTime        string
+	ModifyTime        string
+	DataTimestamp     string
+}
+
+func (m *FactorEdbSeriesCalculateData) Cols() FactorEdbSeriesCalculateDataCols {
+	return FactorEdbSeriesCalculateDataCols{
+		PrimaryId:         "factor_edb_series_calculate_data_id",
+		FactorEdbSeriesId: "factor_edb_series_id",
+		EdbInfoId:         "edb_info_id",
+		EdbCode:           "edb_code",
+		DataTime:          "data_time",
+		Value:             "value",
+		CreateTime:        "create_time",
+		ModifyTime:        "modify_time",
+		DataTimestamp:     "data_timestamp",
+	}
+}
+
+func (m *FactorEdbSeriesCalculateData) Create() (err error) {
+	o := orm.NewOrmUsingDB("data")
+	id, err := o.Insert(m)
+	if err != nil {
+		return
+	}
+	m.FactorEdbSeriesCalculateDataId = int(id)
+	return
+}
+
+func (m *FactorEdbSeriesCalculateData) CreateMulti(items []*FactorEdbSeriesCalculateData) (err error) {
+	if len(items) == 0 {
+		return
+	}
+	o := orm.NewOrmUsingDB("data")
+	_, err = o.InsertMulti(500, items)
+	return
+}
+
+func (m *FactorEdbSeriesCalculateData) Update(cols []string) (err error) {
+	o := orm.NewOrmUsingDB("data")
+	_, err = o.Update(m, cols...)
+	return
+}
+
+func (m *FactorEdbSeriesCalculateData) Remove() (err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.Cols().PrimaryId)
+	_, err = o.Raw(sql, m.FactorEdbSeriesCalculateDataId).Exec()
+	return
+}
+
+func (m *FactorEdbSeriesCalculateData) MultiRemove(ids []int) (err error) {
+	if len(ids) == 0 {
+		return
+	}
+	o := orm.NewOrmUsingDB("data")
+	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s IN (%s)`, m.TableName(), m.Cols().PrimaryId, utils.GetOrmInReplace(len(ids)))
+	_, err = o.Raw(sql, ids).Exec()
+	return
+}
+
+func (m *FactorEdbSeriesCalculateData) RemoveByCondition(condition string, pars []interface{}) (err error) {
+	if condition == "" {
+		return
+	}
+	o := orm.NewOrmUsingDB("data")
+	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s`, m.TableName(), condition)
+	_, err = o.Raw(sql, pars).Exec()
+	return
+}
+
+func (m *FactorEdbSeriesCalculateData) GetItemById(id int) (item *FactorEdbSeriesCalculateData, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.Cols().PrimaryId)
+	err = o.Raw(sql, id).QueryRow(&item)
+	return
+}
+
+func (m *FactorEdbSeriesCalculateData) GetItemByCondition(condition string, pars []interface{}, orderRule string) (item *FactorEdbSeriesCalculateData, err error) {
+	o := orm.NewOrmUsingDB("data")
+	order := ``
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE 1=1 %s %s LIMIT 1`, m.TableName(), condition, order)
+	err = o.Raw(sql, pars).QueryRow(&item)
+	return
+}
+
+func (m *FactorEdbSeriesCalculateData) GetCountByCondition(condition string, pars []interface{}) (count int, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := fmt.Sprintf(`SELECT COUNT(1) FROM %s WHERE 1=1 %s`, m.TableName(), condition)
+	err = o.Raw(sql, pars).QueryRow(&count)
+	return
+}
+
+func (m *FactorEdbSeriesCalculateData) GetItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string) (items []*FactorEdbSeriesCalculateData, err error) {
+	o := orm.NewOrmUsingDB("data")
+	fields := strings.Join(fieldArr, ",")
+	if len(fieldArr) == 0 {
+		fields = `*`
+	}
+	order := fmt.Sprintf(`ORDER BY %s DESC`, m.Cols().CreateTime)
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT %s FROM %s WHERE 1=1 %s %s`, fields, m.TableName(), condition, order)
+	_, err = o.Raw(sql, pars).QueryRows(&items)
+	return
+}
+
+func (m *FactorEdbSeriesCalculateData) GetPageItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string, startSize, pageSize int) (items []*FactorEdbSeriesCalculateData, err error) {
+	o := orm.NewOrmUsingDB("data")
+	fields := strings.Join(fieldArr, ",")
+	if len(fieldArr) == 0 {
+		fields = `*`
+	}
+	order := fmt.Sprintf(`ORDER BY %s DESC`, m.Cols().CreateTime)
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT %s FROM %s WHERE 1=1 %s %s LIMIT ?,?`, fields, m.TableName(), condition, order)
+	_, err = o.Raw(sql, pars, startSize, pageSize).QueryRows(&items)
+	return
+}
+
+// FactorEdbSeriesCalculateDataItem 因子指标系列-计算数据信息
+type FactorEdbSeriesCalculateDataItem struct {
+	DataId            int     `description:"数据ID"`
+	FactorEdbSeriesId int     `description:"因子指标系列ID"`
+	EdbInfoId         int     `description:"指标ID"`
+	EdbCode           string  `description:"指标编码"`
+	DataTime          string  `description:"数据日期"`
+	Value             float64 `description:"数据值"`
+}
+
+func (m *FactorEdbSeriesCalculateData) Format2Item() (item *FactorEdbSeriesCalculateDataItem) {
+	item = new(FactorEdbSeriesCalculateDataItem)
+	item.DataId = m.FactorEdbSeriesCalculateDataId
+	item.FactorEdbSeriesId = m.FactorEdbSeriesId
+	item.EdbInfoId = m.EdbInfoId
+	item.EdbCode = m.EdbCode
+	return
+}
+
+// TransEdbSeriesCalculateData2EdbDataList 转换数据格式
+func TransEdbSeriesCalculateData2EdbDataList(items []*FactorEdbSeriesCalculateData) (list []*EdbDataList) {
+	list = make([]*EdbDataList, 0)
+	for _, v := range items {
+		list = append(list, &EdbDataList{
+			DataTime: v.DataTime.Format(utils.FormatDate),
+			Value:    v.Value,
+		})
+	}
+	return
+}

+ 153 - 0
models/data_manage/factor_edb_series_calculate_func.go

@@ -0,0 +1,153 @@
+package data_manage
+
+import (
+	"eta/eta_mobile/utils"
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
+	"strings"
+	"time"
+)
+
+// FactorEdbSeriesCalculateFunc 多因子系列-计算方式表
+type FactorEdbSeriesCalculateFunc struct {
+	FactorEdbSeriesCalculateFuncId int       `orm:"column(factor_edb_series_calculate_func_id);pk"`
+	CalculateName                  string    `description:"计算方式名称"`
+	Source                         int       `description:"计算方式来源"`
+	EdbInfoType                    int       `description:"指标计算类型:0-普通指标;1-预测指标"`
+	CreateTime                     time.Time `description:"创建时间"`
+	ModifyTime                     time.Time `description:"修改时间"`
+}
+
+func (m *FactorEdbSeriesCalculateFunc) TableName() string {
+	return "factor_edb_series_calculate_func"
+}
+
+type FactorEdbSeriesCalculateFuncCols struct {
+	PrimaryId     string
+	CalculateName string
+	Source        string
+	EdbInfoType   string
+	CreateTime    string
+	ModifyTime    string
+}
+
+func (m *FactorEdbSeriesCalculateFunc) Cols() FactorEdbSeriesCalculateFuncCols {
+	return FactorEdbSeriesCalculateFuncCols{
+		PrimaryId:     "factor_edb_series_calculate_func_id",
+		CalculateName: "calculate_name",
+		Source:        "source",
+		EdbInfoType:   "edb_info_type",
+		CreateTime:    "create_time",
+		ModifyTime:    "modify_time",
+	}
+}
+
+func (m *FactorEdbSeriesCalculateFunc) Create() (err error) {
+	o := orm.NewOrmUsingDB("data")
+	id, err := o.Insert(m)
+	if err != nil {
+		return
+	}
+	m.FactorEdbSeriesCalculateFuncId = int(id)
+	return
+}
+
+func (m *FactorEdbSeriesCalculateFunc) CreateMulti(items []*FactorEdbSeriesCalculateFunc) (err error) {
+	if len(items) == 0 {
+		return
+	}
+	o := orm.NewOrmUsingDB("data")
+	_, err = o.InsertMulti(len(items), items)
+	return
+}
+
+func (m *FactorEdbSeriesCalculateFunc) Update(cols []string) (err error) {
+	o := orm.NewOrmUsingDB("data")
+	_, err = o.Update(m, cols...)
+	return
+}
+
+func (m *FactorEdbSeriesCalculateFunc) Remove() (err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.Cols().PrimaryId)
+	_, err = o.Raw(sql, m.FactorEdbSeriesCalculateFuncId).Exec()
+	return
+}
+
+func (m *FactorEdbSeriesCalculateFunc) MultiRemove(ids []int) (err error) {
+	if len(ids) == 0 {
+		return
+	}
+	o := orm.NewOrmUsingDB("data")
+	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s IN (%s)`, m.TableName(), m.Cols().PrimaryId, utils.GetOrmInReplace(len(ids)))
+	_, err = o.Raw(sql, ids).Exec()
+	return
+}
+
+func (m *FactorEdbSeriesCalculateFunc) GetItemById(id int) (item *FactorEdbSeriesCalculateFunc, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.Cols().PrimaryId)
+	err = o.Raw(sql, id).QueryRow(&item)
+	return
+}
+
+func (m *FactorEdbSeriesCalculateFunc) GetItemByCondition(condition string, pars []interface{}, orderRule string) (item *FactorEdbSeriesCalculateFunc, err error) {
+	o := orm.NewOrmUsingDB("data")
+	order := ``
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE 1=1 %s %s LIMIT 1`, m.TableName(), condition, order)
+	err = o.Raw(sql, pars).QueryRow(&item)
+	return
+}
+
+func (m *FactorEdbSeriesCalculateFunc) GetCountByCondition(condition string, pars []interface{}) (count int, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := fmt.Sprintf(`SELECT COUNT(1) FROM %s WHERE 1=1 %s`, m.TableName(), condition)
+	err = o.Raw(sql, pars).QueryRow(&count)
+	return
+}
+
+func (m *FactorEdbSeriesCalculateFunc) GetItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string) (items []*FactorEdbSeriesCalculateFunc, err error) {
+	o := orm.NewOrmUsingDB("data")
+	fields := strings.Join(fieldArr, ",")
+	if len(fieldArr) == 0 {
+		fields = `*`
+	}
+	order := fmt.Sprintf(`ORDER BY %s DESC`, m.Cols().CreateTime)
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT %s FROM %s WHERE 1=1 %s %s`, fields, m.TableName(), condition, order)
+	_, err = o.Raw(sql, pars).QueryRows(&items)
+	return
+}
+
+func (m *FactorEdbSeriesCalculateFunc) GetPageItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string, startSize, pageSize int) (items []*FactorEdbSeriesCalculateFunc, err error) {
+	o := orm.NewOrmUsingDB("data")
+	fields := strings.Join(fieldArr, ",")
+	if len(fieldArr) == 0 {
+		fields = `*`
+	}
+	order := fmt.Sprintf(`ORDER BY %s DESC`, m.Cols().CreateTime)
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT %s FROM %s WHERE 1=1 %s %s LIMIT ?,?`, fields, m.TableName(), condition, order)
+	_, err = o.Raw(sql, pars, startSize, pageSize).QueryRows(&items)
+	return
+}
+
+// FactorEdbSeriesCalculateFuncItem 多因子系列-计算方式
+type FactorEdbSeriesCalculateFuncItem struct {
+	CalculateName string `description:"计算方式名称"`
+	Source        int    `description:"计算方式来源"`
+}
+
+func (m *FactorEdbSeriesCalculateFunc) Format2Item() (item *FactorEdbSeriesCalculateFuncItem) {
+	item = new(FactorEdbSeriesCalculateFuncItem)
+	item.CalculateName = m.CalculateName
+	item.Source = m.Source
+	return
+}

+ 167 - 0
models/data_manage/factor_edb_series_chart_mapping.go

@@ -0,0 +1,167 @@
+package data_manage
+
+import (
+	"eta/eta_mobile/utils"
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
+	"strings"
+	"time"
+)
+
+const (
+	FactorEdbSeriesChartCalculateTypeCorrelation = 1 // 相关性计算
+)
+
+// FactorEdbSeriesChartMapping 因子指标系列-图表关联
+type FactorEdbSeriesChartMapping struct {
+	FactorEdbSeriesChartMappingId int       `orm:"column(factor_edb_series_chart_mapping_id);pk"`
+	ChartInfoId                   int       `description:"图表ID"`
+	Source                        int       `description:"图表来源, 同chart_info表source"`
+	CalculateType                 int       `description:"计算方式: 1-相关性"`
+	CalculatePars                 string    `description:"计算参数-JSON(如计算窗口等)"`
+	CalculateData                 string    `description:"计算数据-JSON(如相关性矩阵等)"`
+	FactorEdbSeriesId             int       `description:"因子指标系列ID"`
+	EdbInfoId                     int       `description:"指标ID"`
+	EdbUsed                       int       `description:"指标是否使用: 0-否; 1-是"`
+	CreateTime                    time.Time `description:"创建时间"`
+	ModifyTime                    time.Time `description:"修改时间"`
+}
+
+func (m *FactorEdbSeriesChartMapping) TableName() string {
+	return "factor_edb_series_chart_mapping"
+}
+
+type MultipleFactorSeriesChartMappingCols struct {
+	PrimaryId         string
+	ChartInfoId       string
+	Source            string
+	CalculateType     string
+	CalculatePars     string
+	CalculateData     string
+	FactorEdbSeriesId string
+	EdbInfoId         string
+	EdbUsed           string
+	CreateTime        string
+	ModifyTime        string
+}
+
+func (m *FactorEdbSeriesChartMapping) Cols() MultipleFactorSeriesChartMappingCols {
+	return MultipleFactorSeriesChartMappingCols{
+		PrimaryId:         "factor_edb_series_chart_mapping_id",
+		ChartInfoId:       "chart_info_id",
+		Source:            "source",
+		CalculateType:     "calculate_type",
+		CalculatePars:     "calculate_pars",
+		CalculateData:     "calculate_data",
+		FactorEdbSeriesId: "factor_edb_series_id",
+		EdbInfoId:         "edb_info_id",
+		EdbUsed:           "edb_used",
+		CreateTime:        "create_time",
+		ModifyTime:        "modify_time",
+	}
+}
+
+func (m *FactorEdbSeriesChartMapping) Create() (err error) {
+	o := orm.NewOrmUsingDB("data")
+	id, err := o.Insert(m)
+	if err != nil {
+		return
+	}
+	m.FactorEdbSeriesChartMappingId = int(id)
+	return
+}
+
+func (m *FactorEdbSeriesChartMapping) CreateMulti(items []*FactorEdbSeriesChartMapping) (err error) {
+	if len(items) == 0 {
+		return
+	}
+	o := orm.NewOrmUsingDB("data")
+	_, err = o.InsertMulti(len(items), items)
+	return
+}
+
+func (m *FactorEdbSeriesChartMapping) Update(cols []string) (err error) {
+	o := orm.NewOrmUsingDB("data")
+	_, err = o.Update(m, cols...)
+	return
+}
+
+func (m *FactorEdbSeriesChartMapping) Remove() (err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.Cols().PrimaryId)
+	_, err = o.Raw(sql, m.FactorEdbSeriesChartMappingId).Exec()
+	return
+}
+
+func (m *FactorEdbSeriesChartMapping) MultiRemove(ids []int) (err error) {
+	if len(ids) == 0 {
+		return
+	}
+	o := orm.NewOrmUsingDB("data")
+	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s IN (%s)`, m.TableName(), m.Cols().PrimaryId, utils.GetOrmInReplace(len(ids)))
+	_, err = o.Raw(sql, ids).Exec()
+	return
+}
+
+func (m *FactorEdbSeriesChartMapping) GetItemById(id int) (item *FactorEdbSeriesChartMapping, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.Cols().PrimaryId)
+	err = o.Raw(sql, id).QueryRow(&item)
+	return
+}
+
+func (m *FactorEdbSeriesChartMapping) GetItemByCondition(condition string, pars []interface{}, orderRule string) (item *FactorEdbSeriesChartMapping, err error) {
+	o := orm.NewOrmUsingDB("data")
+	order := ``
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE 1=1 %s %s LIMIT 1`, m.TableName(), condition, order)
+	err = o.Raw(sql, pars).QueryRow(&item)
+	return
+}
+
+func (m *FactorEdbSeriesChartMapping) GetCountByCondition(condition string, pars []interface{}) (count int, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := fmt.Sprintf(`SELECT COUNT(1) FROM %s WHERE 1=1 %s`, m.TableName(), condition)
+	err = o.Raw(sql, pars).QueryRow(&count)
+	return
+}
+
+func (m *FactorEdbSeriesChartMapping) GetItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string) (items []*FactorEdbSeriesChartMapping, err error) {
+	o := orm.NewOrmUsingDB("data")
+	fields := strings.Join(fieldArr, ",")
+	if len(fieldArr) == 0 {
+		fields = `*`
+	}
+	order := fmt.Sprintf(`ORDER BY %s DESC`, m.Cols().CreateTime)
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT %s FROM %s WHERE 1=1 %s %s`, fields, m.TableName(), condition, order)
+	_, err = o.Raw(sql, pars).QueryRows(&items)
+	return
+}
+
+func (m *FactorEdbSeriesChartMapping) GetPageItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string, startSize, pageSize int) (items []*FactorEdbSeriesChartMapping, err error) {
+	o := orm.NewOrmUsingDB("data")
+	fields := strings.Join(fieldArr, ",")
+	if len(fieldArr) == 0 {
+		fields = `*`
+	}
+	order := fmt.Sprintf(`ORDER BY %s DESC`, m.Cols().CreateTime)
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT %s FROM %s WHERE 1=1 %s %s LIMIT ?,?`, fields, m.TableName(), condition, order)
+	_, err = o.Raw(sql, pars, startSize, pageSize).QueryRows(&items)
+	return
+}
+
+// GetDistinctSeriesIdByChartId 获取图表关联的系列ID
+func (m *FactorEdbSeriesChartMapping) GetDistinctSeriesIdByChartId(chartId int) (seriesIds []int, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := fmt.Sprintf(`SELECT DISTINCT %s FROM %s WHERE %s = ?`, m.Cols().FactorEdbSeriesId, m.TableName(), m.Cols().ChartInfoId)
+	_, err = o.Raw(sql, chartId).QueryRows(&seriesIds)
+	return
+}

+ 167 - 0
models/data_manage/factor_edb_series_mapping.go

@@ -0,0 +1,167 @@
+package data_manage
+
+import (
+	"eta/eta_mobile/utils"
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
+	"strings"
+	"time"
+)
+
+// FactorEdbSeriesMapping 因子指标系列-指标关联表
+type FactorEdbSeriesMapping struct {
+	FactorEdbSeriesMappingId int       `orm:"column(factor_edb_series_mapping_id);pk"`
+	FactorEdbSeriesId        int       `description:"因子指标系列ID"`
+	EdbInfoId                int       `description:"指标ID"`
+	EdbCode                  string    `description:"指标编码"`
+	CreateTime               time.Time `description:"创建时间"`
+	ModifyTime               time.Time `description:"修改时间"`
+}
+
+func (m *FactorEdbSeriesMapping) TableName() string {
+	return "factor_edb_series_mapping"
+}
+
+type FactorEdbSeriesMappingCols struct {
+	PrimaryId         string
+	FactorEdbSeriesId string
+	EdbInfoId         string
+	EdbCode           string
+	CreateTime        string
+	ModifyTime        string
+}
+
+func (m *FactorEdbSeriesMapping) Cols() FactorEdbSeriesMappingCols {
+	return FactorEdbSeriesMappingCols{
+		PrimaryId:         "factor_edb_series_mapping_id",
+		FactorEdbSeriesId: "factor_edb_series_id",
+		EdbInfoId:         "edb_info_id",
+		EdbCode:           "edb_code",
+		CreateTime:        "create_time",
+		ModifyTime:        "modify_time",
+	}
+}
+
+func (m *FactorEdbSeriesMapping) Create() (err error) {
+	o := orm.NewOrmUsingDB("data")
+	id, err := o.Insert(m)
+	if err != nil {
+		return
+	}
+	m.FactorEdbSeriesMappingId = int(id)
+	return
+}
+
+func (m *FactorEdbSeriesMapping) CreateMulti(items []*FactorEdbSeriesMapping) (err error) {
+	if len(items) == 0 {
+		return
+	}
+	o := orm.NewOrmUsingDB("data")
+	_, err = o.InsertMulti(len(items), items)
+	return
+}
+
+func (m *FactorEdbSeriesMapping) Update(cols []string) (err error) {
+	o := orm.NewOrmUsingDB("data")
+	_, err = o.Update(m, cols...)
+	return
+}
+
+func (m *FactorEdbSeriesMapping) Remove() (err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.Cols().PrimaryId)
+	_, err = o.Raw(sql, m.FactorEdbSeriesMappingId).Exec()
+	return
+}
+
+func (m *FactorEdbSeriesMapping) MultiRemove(ids []int) (err error) {
+	if len(ids) == 0 {
+		return
+	}
+	o := orm.NewOrmUsingDB("data")
+	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s IN (%s)`, m.TableName(), m.Cols().PrimaryId, utils.GetOrmInReplace(len(ids)))
+	_, err = o.Raw(sql, ids).Exec()
+	return
+}
+
+func (m *FactorEdbSeriesMapping) RemoveByCondition(condition string, pars []interface{}) (err error) {
+	if condition == "" {
+		return
+	}
+	o := orm.NewOrmUsingDB("data")
+	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s`, m.TableName(), condition)
+	_, err = o.Raw(sql, pars).Exec()
+	return
+}
+
+func (m *FactorEdbSeriesMapping) GetItemById(id int) (item *FactorEdbSeriesMapping, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.Cols().PrimaryId)
+	err = o.Raw(sql, id).QueryRow(&item)
+	return
+}
+
+func (m *FactorEdbSeriesMapping) GetItemByCondition(condition string, pars []interface{}, orderRule string) (item *FactorEdbSeriesMapping, err error) {
+	o := orm.NewOrmUsingDB("data")
+	order := ``
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE 1=1 %s %s LIMIT 1`, m.TableName(), condition, order)
+	err = o.Raw(sql, pars).QueryRow(&item)
+	return
+}
+
+func (m *FactorEdbSeriesMapping) GetCountByCondition(condition string, pars []interface{}) (count int, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := fmt.Sprintf(`SELECT COUNT(1) FROM %s WHERE 1=1 %s`, m.TableName(), condition)
+	err = o.Raw(sql, pars).QueryRow(&count)
+	return
+}
+
+func (m *FactorEdbSeriesMapping) GetItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string) (items []*FactorEdbSeriesMapping, err error) {
+	o := orm.NewOrmUsingDB("data")
+	fields := strings.Join(fieldArr, ",")
+	if len(fieldArr) == 0 {
+		fields = `*`
+	}
+	order := fmt.Sprintf(`ORDER BY %s DESC`, m.Cols().CreateTime)
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT %s FROM %s WHERE 1=1 %s %s`, fields, m.TableName(), condition, order)
+	_, err = o.Raw(sql, pars).QueryRows(&items)
+	return
+}
+
+func (m *FactorEdbSeriesMapping) GetPageItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string, startSize, pageSize int) (items []*FactorEdbSeriesMapping, err error) {
+	o := orm.NewOrmUsingDB("data")
+	fields := strings.Join(fieldArr, ",")
+	if len(fieldArr) == 0 {
+		fields = `*`
+	}
+	order := fmt.Sprintf(`ORDER BY %s DESC`, m.Cols().CreateTime)
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT %s FROM %s WHERE 1=1 %s %s LIMIT ?,?`, fields, m.TableName(), condition, order)
+	_, err = o.Raw(sql, pars, startSize, pageSize).QueryRows(&items)
+	return
+}
+
+// FactorEdbSeriesMappingItem 因子指标系列-指标关联信息
+type FactorEdbSeriesMappingItem struct {
+	SeriesId  int    `description:"因子指标系列ID"`
+	EdbInfoId int    `description:"指标ID"`
+	EdbCode   string `description:"指标编码"`
+	EdbName   string `description:"指标名称"`
+	EdbNameEn string `description:"指标名称-英文"`
+}
+
+func (m *FactorEdbSeriesMapping) Format2Item() (item *FactorEdbSeriesMappingItem) {
+	item = new(FactorEdbSeriesMappingItem)
+	item.SeriesId = m.FactorEdbSeriesId
+	item.EdbInfoId = m.EdbInfoId
+	item.EdbCode = m.EdbCode
+	return
+}

+ 26 - 8
models/db.go

@@ -193,8 +193,11 @@ func init() {
 	// 初始化数据资产权限的一些表
 	initDataMangePerMission()
 
+	// 初始化因子指标系列
+	initFactorEdbSeries()
+
 	// 初始化部分数据表变量(直接init会有顺序问题=_=!)
-	data_manage.InitEdbSourceVar()
+	afterInitTable()
 }
 
 // initSystem 系统表 数据表
@@ -301,11 +304,6 @@ func initEdbData() {
 		//new(data_manage.EdbdataClassify),
 		//new(data_manage.ManualUser),
 		new(data_manage.EdbInfoCalculate),
-		new(data_manage.EdbDataCalculate),
-		//new(data_manage.EdbInfoCalculateLjzzy),
-		new(data_manage.EdbInfoCalculateTbz),
-		//new(data_manage.EdbInfoCalculateTcz),
-		//new(data_manage.EdbInfoCalculateNszydpjjs),
 		new(data_manage.SearchKeyword),
 		//new(data_manage.EdbInfoCalculateHbz),
 		//new(data_manage.EdbInfoCalculateHcz),
@@ -316,8 +314,6 @@ func initEdbData() {
 		new(data_manage.BaseFromSmmClassify),
 		new(data_manage.EdbInfoLog),
 		new(data_manage.EdbInfoCalculateMapping),
-		new(data_manage.EdbDataCalculateZjpj),            //直接拼接
-		new(data_manage.EdbDataCalculateLjztbpj),         //累计同比值拼接
 		new(data_manage.PredictEdbConf),                  //预测指标配置
 		new(data_manage.BaseFromMysteelChemicalClassify), //预测指标配置
 		new(data_manage.BaseFromMysteelChemicalIndex),    //钢联化工
@@ -596,3 +592,25 @@ func initDataMangePerMission() {
 		new(data_manage_permission.DataPermissionNoAuthRecord),              // 资产数据权限设置记录表
 	)
 }
+
+// initFactorEdbSeries 因子指标系列数据表
+func initFactorEdbSeries() {
+	orm.RegisterModel(
+		new(data_manage.FactorEdbSeries),              // 因子指标系列
+		new(data_manage.FactorEdbSeriesChartMapping),  // 因子指标系列-图表关联
+		new(data_manage.FactorEdbSeriesMapping),       // 因子指标系列-指标计算数据
+		new(data_manage.FactorEdbSeriesCalculateData), // 因子指标系列-指标关联
+	)
+}
+
+// afterInitTable
+// @Description: 初始化表结构的的后置操作
+// @author: Roc
+// @datetime 2024-07-01 13:31:09
+func afterInitTable() {
+	// 初始化指标来源配置
+	data_manage.InitEdbSourceVar()
+
+	// 初始化是否启用mongo配置
+	InitUseMongoConf()
+}

+ 8 - 0
models/english_report.go

@@ -929,3 +929,11 @@ func ModifyEnglishReportImgUrl(reportId int, detailImgUrl string) (err error) {
 	_, err = o.Raw(sql, detailImgUrl, reportId).Exec()
 	return
 }
+
+// UpdatePdfUrlEnglishReportById 清空pdf相关字段
+func UpdatePdfUrlEnglishReportById(reportId int) (err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := `UPDATE english_report SET detail_img_url = '',detail_pdf_url='',modify_time=NOW() WHERE id = ? `
+	_, err = o.Raw(sql, reportId).Exec()
+	return
+}

+ 419 - 0
models/mgo/base_from_business_data.go

@@ -0,0 +1,419 @@
+package mgo
+
+import (
+	"context"
+	"errors"
+	"eta/eta_mobile/utils"
+	"fmt"
+	"github.com/qiniu/qmgo"
+	"go.mongodb.org/mongo-driver/bson"
+	"go.mongodb.org/mongo-driver/bson/primitive"
+	"time"
+)
+
+// BaseFromBusinessData
+// @Description: 自有数据集合
+type BaseFromBusinessData struct {
+	ID primitive.ObjectID `json:"_id" bson:"_id,omitempty"` // 文档id
+	//ID string `json:"_id" bson:"_id" ` // 文档id
+	BaseFromBusinessIndexId int64     `json:"base_from_business_index_id" bson:"base_from_business_index_id"` // 指标id
+	IndexCode               string    `json:"index_code" bson:"index_code"`                                   // 指标编码
+	DataTime                time.Time `json:"data_time" bson:"data_time"`                                     // 数据日期
+	Value                   float64   `json:"value" bson:"value"`                                             // 数据值
+	CreateTime              time.Time `json:"create_time" bson:"create_time"`                                 // 创建时间
+	ModifyTime              time.Time `json:"modify_time" bson:"modify_time"`                                 // 修改时间
+}
+
+// CollectionName
+// @Description:  获取集合名称
+// @author: Roc
+// @receiver m
+// @datetime 2024-04-26 13:41:36
+// @return string
+func (m *BaseFromBusinessData) CollectionName() string {
+	return "base_from_business_data"
+}
+
+// DataBaseName
+// @Description: 获取数据库名称
+// @author: Roc
+// @receiver m
+// @datetime 2024-04-26 13:41:33
+// @return string
+func (m *BaseFromBusinessData) DataBaseName() string {
+	return utils.MgoDataDbName
+}
+
+// GetCollection
+// @Description: 获取mongodb集合的句柄
+// @author: Roc
+// @receiver m
+// @datetime 2024-04-26 13:41:33
+// @return string
+func (m *BaseFromBusinessData) GetCollection() *qmgo.Collection {
+	db := utils.MgoDataCli.Database(m.DataBaseName())
+	return db.Collection(m.CollectionName())
+}
+
+// GetAllDataList
+// @Description: 根据条件获取所有数据
+// @author: Roc
+// @receiver m
+// @datetime 2024-04-26 13:42:19
+// @param sort []string
+// @param whereParams interface{}
+// @return result []BaseFromBusinessData
+// @return err error
+func (m *BaseFromBusinessData) GetAllDataList(whereParams interface{}, sort []string) (result []*BaseFromBusinessData, err error) {
+	if utils.MgoDataCli == nil {
+		err = errors.New("mongodb连接失败")
+		return
+	}
+	db := utils.MgoDataCli.Database(m.DataBaseName())
+	coll := db.Collection(m.CollectionName())
+	ctx := context.TODO()
+	if err != nil {
+		fmt.Println("MgoGetColl Err:", err.Error())
+		return
+	}
+	err = coll.Find(ctx, whereParams).Sort(sort...).All(&result)
+	if err != nil {
+		return
+	}
+
+	for _, v := range result {
+		v.DataTime = v.DataTime.In(time.Local)
+		v.CreateTime = v.CreateTime.In(time.Local)
+		v.ModifyTime = v.ModifyTime.In(time.Local)
+	}
+
+	return
+}
+
+// GetLimitDataList
+// @Description: 根据条件获取指定数量数据列表
+// @author: Roc
+// @receiver m
+// @datetime 2024-05-06 17:08:32
+// @param whereParams interface{}
+// @param size int64
+// @return result []*BaseFromBusinessData
+// @return err error
+func (m *BaseFromBusinessData) GetLimitDataList(whereParams interface{}, size int64, sort []string) (result []*BaseFromBusinessData, err error) {
+	if utils.MgoDataCli == nil {
+		err = errors.New("mongodb连接失败")
+		return
+	}
+	db := utils.MgoDataCli.Database(m.DataBaseName())
+	coll := db.Collection(m.CollectionName())
+	ctx := context.TODO()
+	if err != nil {
+		fmt.Println("MgoGetColl Err:", err.Error())
+		return
+	}
+	err = coll.Find(ctx, whereParams).Sort(sort...).Limit(size).All(&result)
+	if err != nil {
+		return
+	}
+
+	for _, v := range result {
+		v.DataTime = v.DataTime.In(time.Local)
+		v.CreateTime = v.CreateTime.In(time.Local)
+		v.ModifyTime = v.ModifyTime.In(time.Local)
+	}
+
+	return
+}
+
+// GetPageDataList
+// @Description: 根据条件获取分页数据列表
+// @author: Roc
+// @receiver m
+// @datetime 2024-05-07 10:21:07
+// @param whereParams interface{}
+// @param startSize int64
+// @param size int64
+// @param sort []string
+// @return result []*BaseFromBusinessData
+// @return err error
+func (m *BaseFromBusinessData) GetPageDataList(whereParams interface{}, startSize, size int64, sort []string) (result []*BaseFromBusinessData, err error) {
+	if utils.MgoDataCli == nil {
+		err = errors.New("mongodb连接失败")
+		return
+	}
+	db := utils.MgoDataCli.Database(m.DataBaseName())
+	coll := db.Collection(m.CollectionName())
+	ctx := context.TODO()
+	if err != nil {
+		fmt.Println("MgoGetColl Err:", err.Error())
+		return
+	}
+	err = coll.Find(ctx, whereParams).Sort(sort...).Skip(startSize).Limit(size).All(&result)
+	if err != nil {
+		return
+	}
+
+	for _, v := range result {
+		v.DataTime = v.DataTime.In(time.Local)
+		v.CreateTime = v.CreateTime.In(time.Local)
+		v.ModifyTime = v.ModifyTime.In(time.Local)
+	}
+
+	return
+}
+
+// GetCountDataList
+// @Description:  根据条件获取数据列表总数
+// @author: Roc
+// @receiver m
+// @datetime 2024-05-07 10:29:00
+// @param whereParams interface{}
+// @return count int64
+// @return err error
+func (m *BaseFromBusinessData) GetCountDataList(whereParams interface{}) (count int64, err error) {
+	if utils.MgoDataCli == nil {
+		err = errors.New("mongodb连接失败")
+		return
+	}
+	db := utils.MgoDataCli.Database(m.DataBaseName())
+	coll := db.Collection(m.CollectionName())
+	ctx := context.TODO()
+	if err != nil {
+		fmt.Println("MgoGetColl Err:", err.Error())
+		return
+	}
+	count, err = coll.Find(ctx, whereParams).Count()
+
+	return
+}
+
+// InsertDataByColl
+// @Description: 写入单条数据(外部传入集合)
+// @author: Roc
+// @receiver m
+// @datetime 2024-04-26 14:22:18
+// @param addData interface{}
+// @return err error
+func (m *BaseFromBusinessData) InsertDataByColl(coll *qmgo.Collection, addData interface{}) (err error) {
+	ctx := context.TODO()
+	_, err = coll.InsertOne(ctx, addData)
+	if err != nil {
+		fmt.Println("InsertDataByColl:Err:" + err.Error())
+		return
+	}
+
+	return
+}
+
+// BatchInsertData
+// @Description: 批量写入数据
+// @author: Roc
+// @receiver m
+// @datetime 2024-04-26 14:22:18
+// @param bulk int 每次请求保存的数据量
+// @param dataList []interface{}
+// @return err error
+func (m *BaseFromBusinessData) BatchInsertData(bulk int, dataList []interface{}) (err error) {
+	db := utils.MgoDataCli.Database(m.DataBaseName())
+	coll := db.Collection(m.CollectionName())
+
+	return m.BatchInsertDataByColl(coll, bulk, dataList)
+}
+
+// BatchInsertDataByColl
+// @Description: 批量写入数据(外部传入集合)
+// @author: Roc
+// @receiver m
+// @datetime 2024-04-26 14:22:18
+// @param coll *qmgo.Collection
+// @param bulk int 每次请求保存的数据量
+// @param dataList []interface{}
+// @return err error
+func (m *BaseFromBusinessData) BatchInsertDataByColl(coll *qmgo.Collection, bulk int, dataList []interface{}) (err error) {
+	ctx := context.TODO()
+	dataNum := len(dataList)
+	if dataNum <= 0 {
+		return
+	}
+
+	// 不设置每次保存切片数量大小,或者实际数据量小于设置的切片数量大小,那么就直接保存吧
+	if bulk <= 0 || dataNum <= bulk {
+		_, err = coll.InsertMany(ctx, dataList)
+		if err != nil {
+			fmt.Println("BatchInsertData:Err:" + err.Error())
+			return
+		}
+		return
+	}
+
+	// 分批保存
+	i := 0
+	tmpAddDataList := make([]interface{}, 0)
+	for _, v := range dataList {
+		tmpAddDataList = append(tmpAddDataList, v)
+		i++
+		if i >= bulk {
+			_, err = coll.InsertMany(ctx, tmpAddDataList)
+			if err != nil {
+				fmt.Println("BatchInsertData:Err:" + err.Error())
+				return
+			}
+			i = 0
+			tmpAddDataList = make([]interface{}, 0)
+		}
+	}
+
+	if len(tmpAddDataList) > 0 {
+		_, err = coll.InsertMany(ctx, tmpAddDataList)
+		if err != nil {
+			fmt.Println("BatchInsertData:Err:" + err.Error())
+			return
+		}
+	}
+
+	return
+}
+
+// UpdateDataByColl
+// @Description: 单条数据修改
+// @author: Roc
+// @receiver m
+// @datetime 2024-04-26 15:01:51
+// @param whereParams interface{}
+// @param updateParams interface{}
+// @return err error
+func (m *BaseFromBusinessData) UpdateDataByColl(coll *qmgo.Collection, whereParams, updateParams interface{}) (err error) {
+	ctx := context.TODO()
+	err = coll.UpdateOne(ctx, whereParams, updateParams)
+	if err != nil {
+		fmt.Println("UpdateDataByColl:Err:" + err.Error())
+		return
+	}
+	return
+}
+
+// UpdateData
+// @Description: 单条数据修改
+// @author: Roc
+// @receiver m
+// @datetime 2024-04-26 15:01:51
+// @param whereParams interface{}
+// @param updateParams interface{}
+// @return err error
+func (m *BaseFromBusinessData) UpdateData(whereParams, updateParams interface{}) (err error) {
+	db := utils.MgoDataCli.Database(m.DataBaseName())
+	coll := db.Collection(m.CollectionName())
+	ctx := context.TODO()
+	err = coll.UpdateOne(ctx, whereParams, updateParams)
+	if err != nil {
+		fmt.Println("UpdateData:Err:" + err.Error())
+		return
+	}
+	return
+}
+
+// HandleData
+// @Description: 事务处理数据
+// @author: Roc
+// @receiver m
+// @datetime 2024-04-30 10:40:20
+// @param addDataList []BaseAddFromBusinessData
+// @param updateDataList []BaseFromBusinessData
+// @return result interface{}
+// @return err error
+func (m *BaseFromBusinessData) HandleData(addDataList, updateDataList []BaseFromBusinessData) (result interface{}, err error) {
+
+	ctx := context.TODO()
+
+	callback := func(sessCtx context.Context) (interface{}, error) {
+		// 重要:确保事务中的每一个操作,都使用传入的sessCtx参数
+
+		db := utils.MgoDataCli.Database(m.DataBaseName())
+		coll := db.Collection(m.CollectionName())
+
+		// 插入数据
+		if len(addDataList) > 0 {
+			_, err = coll.InsertMany(sessCtx, addDataList)
+			if err != nil {
+				return nil, err
+			}
+		}
+
+		// 修改
+
+		if len(updateDataList) > 0 {
+			for _, v := range updateDataList {
+				err = coll.UpdateOne(ctx, bson.M{"_id": v.ID}, bson.M{"$set": bson.M{"value": v.Value, "modify_time": v.ModifyTime}})
+				if err != nil {
+					fmt.Println("BatchInsertData:Err:" + err.Error())
+					return nil, err
+				}
+			}
+		}
+
+		return nil, nil
+	}
+	result, err = utils.MgoDataCli.DoTransaction(ctx, callback)
+
+	return
+}
+
+// GetEdbInfoMaxAndMinInfo
+// @Description: 获取当前指标的最大最小值
+// @author: Roc
+// @receiver m
+// @datetime 2024-04-30 17:15:39
+// @param whereParams interface{}
+// @return result EdbInfoMaxAndMinInfo
+// @return err error
+func (m *BaseFromBusinessData) GetEdbInfoMaxAndMinInfo(whereParams interface{}) (result EdbInfoMaxAndMinInfo, err error) {
+	if utils.MgoDataCli == nil {
+		err = errors.New("mongodb连接失败")
+		return
+	}
+	db := utils.MgoDataCli.Database(m.DataBaseName())
+	coll := db.Collection(m.CollectionName())
+	ctx := context.TODO()
+	if err != nil {
+		fmt.Println("MgoGetColl Err:", err.Error())
+		return
+	}
+	err = coll.Aggregate(ctx, whereParams).One(&result)
+	if err != nil {
+		return
+	}
+	result.MinDate = result.MinDate.In(time.Local)
+	result.MaxDate = result.MaxDate.In(time.Local)
+	result.LatestDate = result.LatestDate.In(time.Local)
+
+	return
+}
+
+// GetLatestValue
+// @Description: 获取当前指标的最新数据记录
+// @author: Roc
+// @receiver m
+// @datetime 2024-04-30 17:16:15
+// @param whereParams interface{}
+// @param selectParam interface{}
+// @return latestValue LatestValue
+// @return err error
+func (m *BaseFromBusinessData) GetLatestValue(whereParams, selectParam interface{}) (latestValue LatestValue, err error) {
+	if utils.MgoDataCli == nil {
+		err = errors.New("mongodb连接失败")
+		return
+	}
+	db := utils.MgoDataCli.Database(m.DataBaseName())
+	coll := db.Collection(m.CollectionName())
+	ctx := context.TODO()
+	if err != nil {
+		fmt.Println("MgoGetColl Err:", err.Error())
+		return
+	}
+
+	//var result interface{}
+	//err = coll.Find(ctx, whereParams).Select(selectParam).One(&result)
+	err = coll.Find(ctx, whereParams).Select(selectParam).One(&latestValue)
+
+	return
+}

+ 58 - 0
models/mgo/common.go

@@ -0,0 +1,58 @@
+package mgo
+
+import (
+	"eta/eta_mobile/utils"
+	"go.mongodb.org/mongo-driver/bson"
+	"time"
+)
+
+// BuildDateCondition
+// @Description:  构建日期查询条件
+// @author: Roc
+// @datetime 2024-06-03 09:41:19
+// @param start string
+// @param end string
+// @return condition bson.M
+// @return err error
+func BuildDateCondition(start, end string) (condition bson.M, err error) {
+	var startDateTime, endDateTime time.Time
+	if start != "" {
+		// 使用开始日期条件
+		startDateTime, err = time.ParseInLocation(utils.FormatDate, start, time.Local)
+		if err != nil {
+			return
+		}
+	}
+	if end != "" {
+		// 使用结束日期条件
+		endDateTime, err = time.ParseInLocation(utils.FormatDate, end, time.Local)
+		if err != nil {
+			return
+		}
+	}
+
+	return BuildDateTimeCondition(startDateTime, endDateTime)
+
+}
+
+// BuildDateTimeCondition
+// @Description: 构建日期查询条件
+// @author: Roc
+// @datetime 2024-06-03 09:47:32
+// @param startDateTime time.Time
+// @param endDateTime time.Time
+// @return condition bson.M
+// @return err error
+func BuildDateTimeCondition(startDateTime, endDateTime time.Time) (condition bson.M, err error) {
+	if !startDateTime.IsZero() && !endDateTime.IsZero() {
+		condition = bson.M{utils.DateConvMysqlConvMongo(">="): startDateTime, utils.DateConvMysqlConvMongo("<="): endDateTime}
+	} else if !startDateTime.IsZero() {
+		cond := utils.DateConvMysqlConvMongo(">=")
+		condition = bson.M{cond: startDateTime}
+	} else if !endDateTime.IsZero() {
+		cond := utils.DateConvMysqlConvMongo("<=")
+		condition = bson.M{cond: endDateTime}
+	}
+
+	return
+}

+ 511 - 0
models/mgo/edb_data_business.go

@@ -0,0 +1,511 @@
+package mgo
+
+import (
+	"context"
+	"errors"
+	"eta/eta_mobile/utils"
+	"fmt"
+	"github.com/qiniu/qmgo"
+	"go.mongodb.org/mongo-driver/bson"
+	"go.mongodb.org/mongo-driver/bson/primitive"
+	"time"
+)
+
+// EdbDataBusiness
+// @Description: 自有数据集合(指标库)
+type EdbDataBusiness struct {
+	ID            primitive.ObjectID `json:"_id" bson:"_id,omitempty" `            // 文档id
+	EdbInfoId     int                `json:"edb_info_id" bson:"edb_info_id"`       // 指标编码
+	EdbCode       string             `json:"edb_code" bson:"edb_code"`             // 指标编码
+	DataTime      time.Time          `json:"data_time" bson:"data_time"`           // 数据日期
+	Value         float64            `json:"value" bson:"value"`                   // 数据值
+	CreateTime    time.Time          `json:"create_time" bson:"create_time"`       // 创建时间
+	ModifyTime    time.Time          `json:"modify_time" bson:"modify_time"`       // 修改时间
+	DataTimestamp int64              `json:"data_timestamp" bson:"data_timestamp"` // 数据日期时间戳
+}
+
+// CollectionName
+// @Description:  获取集合名称
+// @author: Roc
+// @receiver m
+// @datetime 2024-04-26 13:41:36
+// @return string
+func (m *EdbDataBusiness) CollectionName() string {
+	return "edb_data_business"
+}
+
+// DataBaseName
+// @Description: 获取数据库名称
+// @author: Roc
+// @receiver m
+// @datetime 2024-04-26 13:41:33
+// @return string
+func (m *EdbDataBusiness) DataBaseName() string {
+	return utils.MgoDataDbName
+}
+
+// GetCollection
+// @Description: 获取mongodb集合的句柄
+// @author: Roc
+// @receiver m
+// @datetime 2024-04-26 13:41:33
+// @return string
+func (m *EdbDataBusiness) GetCollection() *qmgo.Collection {
+	db := utils.MgoDataCli.Database(m.DataBaseName())
+	return db.Collection(m.CollectionName())
+}
+
+// GetItem
+// @Description: 根据条件获取单条数据
+// @author: Roc
+// @receiver m
+// @datetime 2024-05-09 10:00:49
+// @param whereParams interface{}
+// @return item *EdbDataBusiness
+// @return err error
+func (m *EdbDataBusiness) GetItem(whereParams interface{}) (item *EdbDataBusiness, err error) {
+	if utils.MgoDataCli == nil {
+		err = errors.New("mongodb连接失败")
+		return
+	}
+	db := utils.MgoDataCli.Database(m.DataBaseName())
+	coll := db.Collection(m.CollectionName())
+
+	return m.GetItemByColl(coll, whereParams)
+}
+
+// GetItemByColl
+// @Description: 根据条件获取单条数据
+// @author: Roc
+// @receiver m
+// @datetime 2024-05-09 13:22:06
+// @param coll *qmgo.Collection
+// @param whereParams interface{}
+// @return item *EdbDataBusiness
+// @return err error
+func (m *EdbDataBusiness) GetItemByColl(coll *qmgo.Collection, whereParams interface{}) (item *EdbDataBusiness, err error) {
+	ctx := context.TODO()
+	if err != nil {
+		fmt.Println("MgoGetColl Err:", err.Error())
+		return
+	}
+	err = coll.Find(ctx, whereParams).One(&item)
+	if err != nil {
+		return
+	}
+
+	item.DataTime = item.DataTime.In(time.Local)
+	item.CreateTime = item.CreateTime.In(time.Local)
+	item.ModifyTime = item.ModifyTime.In(time.Local)
+
+	return
+}
+
+// GetAllDataList
+// @Description: 根据条件获取所有数据
+// @author: Roc
+// @receiver m
+// @datetime 2024-04-26 13:42:19
+// @param whereParams interface{}
+// @param sort []string
+// @return result []EdbDataBusiness
+// @return err error
+func (m *EdbDataBusiness) GetAllDataList(whereParams interface{}, sort []string) (result []*EdbDataBusiness, err error) {
+	if utils.MgoDataCli == nil {
+		err = errors.New("mongodb连接失败")
+		return
+	}
+	db := utils.MgoDataCli.Database(m.DataBaseName())
+	coll := db.Collection(m.CollectionName())
+	ctx := context.TODO()
+	if err != nil {
+		fmt.Println("MgoGetColl Err:", err.Error())
+		return
+	}
+	err = coll.Find(ctx, whereParams).Sort(sort...).All(&result)
+	if err != nil {
+		return
+	}
+
+	for _, v := range result {
+		v.DataTime = v.DataTime.In(time.Local)
+		v.CreateTime = v.CreateTime.In(time.Local)
+		v.ModifyTime = v.ModifyTime.In(time.Local)
+	}
+
+	return
+}
+
+// GetLimitDataList
+// @Description: 根据条件获取指定数量数据列表
+// @author: Roc
+// @receiver m
+// @datetime 2024-05-06 17:08:32
+// @param whereParams interface{}
+// @param size int64
+// @param sort []string
+// @return result []*BaseFromBusinessData
+// @return err error
+func (m *EdbDataBusiness) GetLimitDataList(whereParams interface{}, size int64, sort []string) (result []*EdbDataBusiness, err error) {
+	if utils.MgoDataCli == nil {
+		err = errors.New("mongodb连接失败")
+		return
+	}
+	db := utils.MgoDataCli.Database(m.DataBaseName())
+	coll := db.Collection(m.CollectionName())
+	ctx := context.TODO()
+	if err != nil {
+		fmt.Println("MgoGetColl Err:", err.Error())
+		return
+	}
+	err = coll.Find(ctx, whereParams).Sort(sort...).Limit(size).All(&result)
+	if err != nil {
+		return
+	}
+
+	for _, v := range result {
+		v.DataTime = v.DataTime.In(time.Local)
+		v.CreateTime = v.CreateTime.In(time.Local)
+		v.ModifyTime = v.ModifyTime.In(time.Local)
+	}
+
+	return
+}
+
+// GetPageDataList
+// @Description: 根据条件获取分页数据列表
+// @author: Roc
+// @receiver m
+// @datetime 2024-05-07 10:21:07
+// @param whereParams interface{}
+// @param startSize int64
+// @param size int64
+// @param sort []string
+// @return result []*EdbDataBusiness
+// @return err error
+func (m *EdbDataBusiness) GetPageDataList(whereParams interface{}, startSize, size int64, sort []string) (result []*EdbDataBusiness, err error) {
+	if utils.MgoDataCli == nil {
+		err = errors.New("mongodb连接失败")
+		return
+	}
+	db := utils.MgoDataCli.Database(m.DataBaseName())
+	coll := db.Collection(m.CollectionName())
+	ctx := context.TODO()
+	if err != nil {
+		fmt.Println("MgoGetColl Err:", err.Error())
+		return
+	}
+	err = coll.Find(ctx, whereParams).Sort(sort...).Skip(startSize).Limit(size).All(&result)
+	if err != nil {
+		return
+	}
+
+	for _, v := range result {
+		v.DataTime = v.DataTime.In(time.Local)
+		v.CreateTime = v.CreateTime.In(time.Local)
+		v.ModifyTime = v.ModifyTime.In(time.Local)
+	}
+
+	return
+}
+
+// GetCountDataList
+// @Description:  根据条件获取数据列表总数
+// @author: Roc
+// @receiver m
+// @datetime 2024-05-07 10:29:00
+// @param whereParams interface{}
+// @return count int64
+// @return err error
+func (m *EdbDataBusiness) GetCountDataList(whereParams interface{}) (count int64, err error) {
+	if utils.MgoDataCli == nil {
+		err = errors.New("mongodb连接失败")
+		return
+	}
+	db := utils.MgoDataCli.Database(m.DataBaseName())
+	coll := db.Collection(m.CollectionName())
+	ctx := context.TODO()
+	if err != nil {
+		fmt.Println("MgoGetColl Err:", err.Error())
+		return
+	}
+	count, err = coll.Find(ctx, whereParams).Count()
+
+	return
+}
+
+// InsertDataByColl
+// @Description: 写入单条数据(外部传入集合)
+// @author: Roc
+// @receiver m
+// @datetime 2024-04-26 14:22:18
+// @param addData interface{}
+// @return err error
+func (m *EdbDataBusiness) InsertDataByColl(coll *qmgo.Collection, addData interface{}) (err error) {
+	ctx := context.TODO()
+	_, err = coll.InsertOne(ctx, addData)
+	if err != nil {
+		fmt.Println("InsertDataByColl:Err:" + err.Error())
+		return
+	}
+
+	return
+}
+
+// BatchInsertData
+// @Description: 批量写入数据
+// @author: Roc
+// @receiver m
+// @datetime 2024-04-26 14:22:18
+// @param bulk int 每次请求保存的数据量
+// @param dataList []interface{}
+// @return err error
+func (m *EdbDataBusiness) BatchInsertData(bulk int, dataList []interface{}) (err error) {
+	db := utils.MgoDataCli.Database(m.DataBaseName())
+	coll := db.Collection(m.CollectionName())
+
+	return m.BatchInsertDataByColl(coll, bulk, dataList)
+}
+
+// BatchInsertDataByColl
+// @Description: 批量写入数据(外部传入集合)
+// @author: Roc
+// @receiver m
+// @datetime 2024-04-26 14:22:18
+// @param coll *qmgo.Collection
+// @param bulk int 每次请求保存的数据量
+// @param dataList []interface{}
+// @return err error
+func (m *EdbDataBusiness) BatchInsertDataByColl(coll *qmgo.Collection, bulk int, dataList []interface{}) (err error) {
+	ctx := context.TODO()
+	dataNum := len(dataList)
+	if dataNum <= 0 {
+		return
+	}
+
+	// 不设置每次保存切片数量大小,或者实际数据量小于设置的切片数量大小,那么就直接保存吧
+	if bulk <= 0 || dataNum <= bulk {
+		_, err = coll.InsertMany(ctx, dataList)
+		if err != nil {
+			fmt.Println("BatchInsertData:Err:" + err.Error())
+			return
+		}
+		return
+	}
+
+	// 分批保存
+	i := 0
+	tmpAddDataList := make([]interface{}, 0)
+	for _, v := range dataList {
+		tmpAddDataList = append(tmpAddDataList, v)
+		i++
+		if i >= bulk {
+			_, err = coll.InsertMany(ctx, tmpAddDataList)
+			if err != nil {
+				fmt.Println("BatchInsertData:Err:" + err.Error())
+				return
+			}
+			i = 0
+			tmpAddDataList = make([]interface{}, 0)
+		}
+	}
+
+	if len(tmpAddDataList) > 0 {
+		_, err = coll.InsertMany(ctx, tmpAddDataList)
+		if err != nil {
+			fmt.Println("BatchInsertData:Err:" + err.Error())
+			return
+		}
+	}
+
+	return
+}
+
+// UpdateData
+// @Description: 单条数据修改
+// @author: Roc
+// @receiver m
+// @datetime 2024-04-26 15:01:51
+// @param whereParams interface{}
+// @param updateParams interface{}
+// @return err error
+func (m *EdbDataBusiness) UpdateData(whereParams, updateParams interface{}) (err error) {
+	db := utils.MgoDataCli.Database(m.DataBaseName())
+	coll := db.Collection(m.CollectionName())
+
+	return m.UpdateDataByColl(coll, whereParams, updateParams)
+}
+
+// UpdateDataByColl
+// @Description: 单条数据修改(外部传入集合)
+// @author: Roc
+// @receiver m
+// @datetime 2024-04-26 15:01:51
+// @param whereParams interface{}
+// @param updateParams interface{}
+// @return err error
+func (m *EdbDataBusiness) UpdateDataByColl(coll *qmgo.Collection, whereParams, updateParams interface{}) (err error) {
+	ctx := context.TODO()
+	err = coll.UpdateOne(ctx, whereParams, updateParams)
+	if err != nil {
+		fmt.Println("UpdateDataByColl:Err:" + err.Error())
+		return
+	}
+
+	return
+}
+
+// RemoveMany
+// @Description: 根据条件删除多条数据
+// @author: Roc
+// @receiver m
+// @datetime 2024-04-30 13:17:02
+// @param whereParams interface{}
+// @return err error
+func (m *EdbDataBusiness) RemoveMany(whereParams interface{}) (err error) {
+	db := utils.MgoDataCli.Database(m.DataBaseName())
+	coll := db.Collection(m.CollectionName())
+
+	return m.RemoveManyByColl(coll, whereParams)
+}
+
+// RemoveManyByColl
+// @Description: 根据条件删除多条数据(外部传入集合)
+// @author: Roc
+// @receiver m
+// @datetime 2024-04-30 13:18:42
+// @param coll *qmgo.Collection
+// @param whereParams interface{}
+// @return err error
+func (m *EdbDataBusiness) RemoveManyByColl(coll *qmgo.Collection, whereParams interface{}) (err error) {
+	ctx := context.TODO()
+	_, err = coll.RemoveAll(ctx, whereParams)
+	if err != nil {
+		fmt.Println("RemoveManyByColl:Err:" + err.Error())
+		return
+	}
+
+	return
+}
+
+// HandleData
+// @Description: 事务处理数据
+// @author: Roc
+// @receiver m
+// @datetime 2024-04-30 10:39:01
+// @param addDataList []AddEdbDataBusiness
+// @param updateDataList []EdbDataBusiness
+// @return result interface{}
+// @return err error
+func (m *EdbDataBusiness) HandleData(addDataList, updateDataList []EdbDataBusiness) (result interface{}, err error) {
+
+	ctx := context.TODO()
+
+	callback := func(sessCtx context.Context) (interface{}, error) {
+		// 重要:确保事务中的每一个操作,都使用传入的sessCtx参数
+
+		db := utils.MgoDataCli.Database(m.DataBaseName())
+		coll := db.Collection(m.CollectionName())
+
+		// 插入数据
+		if len(addDataList) > 0 {
+			_, err = coll.InsertMany(sessCtx, addDataList)
+			if err != nil {
+				return nil, err
+			}
+		}
+
+		// 修改
+
+		if len(updateDataList) > 0 {
+			for _, v := range updateDataList {
+				err = coll.UpdateOne(ctx, bson.M{"_id": v.ID}, bson.M{"$set": bson.M{"value": v.Value, "modify_time": v.ModifyTime}})
+				if err != nil {
+					fmt.Println("BatchInsertData:Err:" + err.Error())
+					return nil, err
+				}
+			}
+		}
+
+		return nil, nil
+	}
+	result, err = utils.MgoDataCli.DoTransaction(ctx, callback)
+
+	return
+}
+
+// EdbInfoMaxAndMinInfo 指标最新数据记录结构体
+type EdbInfoMaxAndMinInfo struct {
+	MinDate     time.Time `description:"最小日期" bson:"min_date"`
+	MaxDate     time.Time `description:"最大日期" bson:"max_date"`
+	MinValue    float64   `description:"最小值" bson:"min_value"`
+	MaxValue    float64   `description:"最大值" bson:"max_value"`
+	LatestValue float64   `description:"最新值" bson:"latest_value"`
+	LatestDate  time.Time `description:"实际数据最新日期" bson:"latest_date"`
+	EndValue    float64   `description:"最新值" bson:"end_value"`
+}
+
+// GetEdbInfoMaxAndMinInfo
+// @Description: 获取当前指标的最大最小值
+// @author: Roc
+// @receiver m
+// @datetime 2024-04-30 17:15:39
+// @param whereParams interface{}
+// @return result EdbInfoMaxAndMinInfo
+// @return err error
+func (m *EdbDataBusiness) GetEdbInfoMaxAndMinInfo(whereParams interface{}) (result EdbInfoMaxAndMinInfo, err error) {
+	if utils.MgoDataCli == nil {
+		err = errors.New("mongodb连接失败")
+		return
+	}
+	db := utils.MgoDataCli.Database(m.DataBaseName())
+	coll := db.Collection(m.CollectionName())
+	ctx := context.TODO()
+	if err != nil {
+		fmt.Println("MgoGetColl Err:", err.Error())
+		return
+	}
+	err = coll.Aggregate(ctx, whereParams).One(&result)
+	if err != nil {
+		return
+	}
+	result.MinDate = result.MinDate.In(time.Local)
+	result.MaxDate = result.MaxDate.In(time.Local)
+	result.LatestDate = result.LatestDate.In(time.Local)
+
+	return
+}
+
+// LatestValue 指标最新数据记录结构体
+type LatestValue struct {
+	Value float64 `description:"值" bson:"value"`
+}
+
+// GetLatestValue
+// @Description: 获取当前指标的最新数据记录
+// @author: Roc
+// @receiver m
+// @datetime 2024-04-30 17:16:15
+// @param whereParams interface{}
+// @param selectParam interface{}
+// @return latestValue LatestValue
+// @return err error
+func (m *EdbDataBusiness) GetLatestValue(whereParams, selectParam interface{}) (latestValue LatestValue, err error) {
+	if utils.MgoDataCli == nil {
+		err = errors.New("mongodb连接失败")
+		return
+	}
+	db := utils.MgoDataCli.Database(m.DataBaseName())
+	coll := db.Collection(m.CollectionName())
+	ctx := context.TODO()
+	if err != nil {
+		fmt.Println("MgoGetColl Err:", err.Error())
+		return
+	}
+
+	//var result interface{}
+	//err = coll.Find(ctx, whereParams).Select(selectParam).One(&result)
+	err = coll.Find(ctx, whereParams).Select(selectParam).One(&latestValue)
+
+	return
+}

+ 274 - 0
models/mgo_base.go

@@ -0,0 +1,274 @@
+package models
+
+import (
+	"context"
+	"encoding/json"
+	"errors"
+	"eta/eta_mobile/utils"
+	"eta/eta_mobile/utils/mgodb"
+	"fmt"
+)
+
+func init() {
+	if utils.MgoUrlData != `` {
+		var mgoConfig mgodb.MgoConfig
+		if e := json.Unmarshal([]byte(utils.MgoUrlData), &mgoConfig); e != nil {
+			panic("mongodb链接失败,Err:" + e.Error())
+			return
+		}
+
+		mgoCli := mgodb.MgoNewClient(mgoConfig)
+		utils.MgoDataCli = mgoCli
+		utils.MgoDataDbName = mgoConfig.Database
+		//result, err := TestMgoFindOne("data_ths", bson.M{"edbcode": "s0033227", "datatime": "2015-12-04"})
+		//fmt.Println(time.Now())
+		//result, err := TestMgoFindOne("data_wind", bson.M{"edbcode": "s0033227", "datatime": "2007-12-29"})
+		//fmt.Println(time.Now())
+		//
+		//fmt.Println(err)
+		//fmt.Println(result)
+	}
+
+}
+
+// TestMgoFindOne
+// @Description: 获取单条数据
+// @author: Roc
+// @datetime 2024-04-25 15:44:07
+// @param colName string 集合名词:`data_ths`
+// @param whereParams interface{} bson.M{"edbcode": "s0033227", "datatime": "2015-12-04"}
+// @return result interface{}
+// @return err error
+func TestMgoFindOne(colName string, whereParams interface{}) (result interface{}, err error) {
+	if colName == "" {
+		err = errors.New("集合名称不可为空")
+		return
+	}
+	if utils.MgoDataCli == nil {
+		err = errors.New("mongodb连接失败")
+		return
+	}
+	db := utils.MgoDataCli.Database("hz_data")
+	coll := db.Collection("data_ths")
+	ctx := context.TODO()
+	if err != nil {
+		fmt.Println("MgoGetColl Err:", err.Error())
+		return
+	}
+	//err = coll.Find(ctx, whereParams).One(&result)
+	err = coll.Find(ctx, whereParams).All(&result)
+	return
+}
+
+// 创建集合
+//func MgoCreateCollection(collectionName string) (err error) {
+//	ctx := context.TODO()
+//
+//	mgoClient := mgodb.MgoNewClient()
+//
+//	defer func() {
+//		mgoClient.Close(ctx)
+//	}()
+//
+//	colName := collectionName
+//	err = mgoClient.Database("hz_data").CreateCollection(ctx, colName)
+//	return
+//}
+
+// 批量新增多条数据
+func MgoBatchInsertData(colName string, dataList interface{}) (err error) {
+	if colName == "" {
+		err = errors.New("集合名称不可为空")
+		return
+	}
+	ctx := context.TODO()
+	coll, err := mgodb.MgoGetColl(colName)
+	if err != nil {
+		fmt.Println("MgoGetColl Err:", err.Error())
+		return
+	}
+	defer func() {
+		coll.Close(ctx)
+	}()
+	_, err = coll.Collection.InsertMany(ctx, dataList)
+	if err != nil {
+		fmt.Println("InsertMany:Err:" + err.Error())
+		return
+	}
+	return
+}
+
+// 插入单条数据
+func MgoInsertData(colName string, dataItem interface{}) (insertedID interface{}, err error) {
+	if colName == "" {
+		err = errors.New("集合名称不可为空")
+		return
+	}
+	ctx := context.TODO()
+	coll, err := mgodb.MgoGetColl(colName)
+	if err != nil {
+		fmt.Println("MgoGetColl Err:", err.Error())
+		return
+	}
+	defer func() {
+		coll.Close(ctx)
+	}()
+	result, err := coll.Collection.InsertOne(ctx, dataItem)
+	if err != nil {
+		return
+	}
+	insertedID = result.InsertedID
+	return
+}
+
+/*
+删除数据
+colName := `data_gl`
+whereParams := bson.M{"edbcode": "s0033227"}
+err := MgoRemove(colName, whereParams)
+*/
+func MgoRemove(colName string, whereParams interface{}) (err error) {
+	if colName == "" {
+		err = errors.New("集合名称不可为空")
+		return
+	}
+	ctx := context.TODO()
+	coll, err := mgodb.MgoGetColl(colName)
+	if err != nil {
+		fmt.Println("MgoGetColl Err:", err.Error())
+		return
+	}
+	defer func() {
+		coll.Close(ctx)
+	}()
+	err = coll.Remove(ctx, whereParams)
+	return
+}
+
+/*
+删除多条数据
+colName := `data_gl`
+whereParams := bson.M{"edbcode": "s0033227"}
+err := MgoRemoveAll(colName, whereParams)
+*/
+func MgoRemoveAll(colName string, whereParams interface{}) (count int64, err error) {
+	if colName == "" {
+		err = errors.New("集合名称不可为空")
+		return
+	}
+	ctx := context.TODO()
+	coll, err := mgodb.MgoGetColl(colName)
+	if err != nil {
+		fmt.Println("MgoGetColl Err:", err.Error())
+		return
+	}
+	defer func() {
+		coll.Close(ctx)
+	}()
+	res, err := coll.RemoveAll(ctx, whereParams)
+	if err != nil {
+		fmt.Println("RemoveAll Err:", err.Error())
+		return
+	}
+	count = res.DeletedCount
+	return
+}
+
+/*
+修改单条数据
+colName := `data_ths`
+whereParams := bson.M{"edbcode": "s0033227", "datatime": "2015-12-04"}
+params := bson.M{"$set": bson.M{"value": "1000"}}
+*/
+func MgoUpdateData(colName string, params, whereParams interface{}) (err error) {
+	if colName == "" {
+		err = errors.New("集合名称不可为空")
+		return
+	}
+	ctx := context.TODO()
+	coll, err := mgodb.MgoGetColl(colName)
+	if err != nil {
+		fmt.Println("MgoGetColl Err:", err.Error())
+		return
+	}
+	defer func() {
+		coll.Close(ctx)
+	}()
+	err = coll.UpdateOne(ctx, whereParams, params)
+	return
+}
+
+/*
+获取单条数据
+colName := `data_ths`
+whereParams := bson.M{"edbcode": "s0033227", "datatime": "2015-12-04"}
+*/
+func MgoFindOne(colName string, whereParams interface{}) (result interface{}, err error) {
+	if colName == "" {
+		err = errors.New("集合名称不可为空")
+		return
+	}
+	ctx := context.TODO()
+	coll, err := mgodb.MgoGetColl(colName)
+	if err != nil {
+		fmt.Println("MgoGetColl Err:", err.Error())
+		return
+	}
+	defer func() {
+		coll.Close(ctx)
+	}()
+	err = coll.Find(ctx, whereParams).One(&result)
+	return
+}
+
+/*
+分页获取数据
+colName := `data_ths`
+whereParams := bson.M{"edbcode": "s0033227", "datatime": "2015-12-04"}
+
+sort:="-weight"
+skip:0
+limit:10
+*/
+func MgoBatchFind(colName, sort string, whereParams interface{}, skip, limit int64) (list []interface{}, err error) {
+	if colName == "" {
+		err = errors.New("集合名称不可为空")
+		return
+	}
+	ctx := context.TODO()
+	coll, err := mgodb.MgoGetColl(colName)
+	if err != nil {
+		fmt.Println("MgoGetColl Err:", err.Error())
+		return
+	}
+	defer func() {
+		coll.Close(ctx)
+	}()
+	err = coll.Find(ctx, whereParams).Sort(sort).Skip(skip).Limit(limit).All(&list)
+	return
+}
+
+/*
+MgoUpsertData
+更新插入数据-数据存在即更新, 否则新增
+colName := `data_ths`
+filter := bson.M{"edbcode": "s0033227", "datatime": "2015-12-04"}
+replacement := bson.M{"edb_info_id":0,"edb_code":m.EdbCode,"data_time":d.DataTime,"value":f,"create_time":now,"modify_time":now,"data_timestamp": stamp}
+*/
+func MgoUpsertData(colName string, filter, replacement interface{}) (err error) {
+	if colName == "" {
+		err = errors.New("集合名称不可为空")
+		return
+	}
+	ctx := context.TODO()
+	coll, err := mgodb.MgoGetColl(colName)
+	if err != nil {
+		fmt.Println("MgoGetColl Err:", err.Error())
+		return
+	}
+	defer func() {
+		_ = coll.Close(ctx)
+	}()
+	_, err = coll.Upsert(ctx, filter, replacement)
+	return
+}

+ 9 - 0
models/report.go

@@ -1172,4 +1172,13 @@ func ModifyReportImgUrl(reportId int, detailImgUrl string) (err error) {
 	sql := `UPDATE report SET detail_img_url=? WHERE id=? `
 	_, err = o.Raw(sql, detailImgUrl, reportId).Exec()
 	return
+}
+
+
+// UpdatePdfUrlReportById 清空pdf相关字段
+func UpdatePdfUrlReportById(reportId int) (err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := `UPDATE report SET detail_img_url = '',detail_pdf_url='',modify_time=NOW() WHERE id = ? `
+	_, err = o.Raw(sql, reportId).Exec()
+	return
 }

+ 9 - 0
models/smart_report/smart_report.go

@@ -418,3 +418,12 @@ func UpdateSmartReportsStateBySecondIds(oldState, newState int, secondIds []int)
 	_, err = o.Raw(sql, oldState, newState, secondIds).Exec()
 	return
 }
+
+
+// UpdatePdfUrlSmartReportById 清空pdf相关字段
+func UpdatePdfUrlSmartReportById(reportId int) (err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := `UPDATE smart_report SET detail_img_url = '',detail_pdf_url='',modify_time=NOW() WHERE smart_report_id = ? `
+	_, err = o.Raw(sql, reportId).Exec()
+	return
+}

+ 27 - 0
routers/commentsRouter.go

@@ -754,6 +754,15 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/excel:ExcelInfoController"] = append(beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/excel:ExcelInfoController"],
+        beego.ControllerComments{
+            Method: "DeleteBalanceChart",
+            Router: `/excel_info/balance/chart_del`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/excel:ExcelInfoController"] = append(beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/excel:ExcelInfoController"],
         beego.ControllerComments{
             Method: "GetBaseEdbInfo",
@@ -808,6 +817,15 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/excel:ExcelInfoController"] = append(beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/excel:ExcelInfoController"],
+        beego.ControllerComments{
+            Method: "GetEdbSource",
+            Router: `/excel_info/get_edb_source`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/excel:ExcelInfoController"] = append(beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/excel:ExcelInfoController"],
         beego.ControllerComments{
             Method: "GetSystemDate",
@@ -1024,6 +1042,15 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/future_good:FutureGoodChartInfoController"] = append(beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/future_good:FutureGoodChartInfoController"],
+        beego.ControllerComments{
+            Method: "BaseInfoEdit",
+            Router: `/chart_info/base/edit`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/future_good:FutureGoodChartInfoController"] = append(beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage/future_good:FutureGoodChartInfoController"],
         beego.ControllerComments{
             Method: "ChartInfoBase64Upload",

+ 25 - 0
services/data/base_edb_lib.go

@@ -472,6 +472,31 @@ func BaseCalculate(param, lang string) (resp *BaseCalculateResp, err error) {
 	return
 }
 
+// AddBaseEdbInfo 新增基础指标
+func AddBaseEdbInfo(addBaseEdbInfoReqStr string, source, subSource int, lang string) (resp *AddPredictEdbDataResponse, err error) {
+	urlStr := ``
+	switch source {
+	case utils.DATA_SOURCE_BUSINESS:
+		urlStr = "business_index/add"
+	default:
+		edbSource := data_manage.EdbSourceIdMap[source]
+		if edbSource != nil {
+			urlStr = edbSource.EdbRefreshMethod
+		}
+	}
+	if urlStr == "" {
+		err = fmt.Errorf(fmt.Sprint("source:", source, ";未实现该指标的刷新接口,请联系管理员"))
+		return
+	}
+	_, resultByte, err := postAddEdbData(addBaseEdbInfoReqStr, urlStr, lang)
+	if err != nil {
+		return
+	}
+	err = json.Unmarshal(resultByte, &resp)
+
+	return
+}
+
 // postRefreshEdbData 刷新指标数据
 func postRefreshEdbData(param map[string]interface{}, urlStr string) (resp *models.BaseResponse, err error) {
 	postUrl := utils.EDB_LIB_URL + urlStr

+ 172 - 0
services/data/base_from_business.go

@@ -0,0 +1,172 @@
+package data
+
+import (
+	"eta/eta_mobile/models/data_manage"
+	"eta/eta_mobile/models/mgo"
+	"eta/eta_mobile/utils"
+	"fmt"
+	"go.mongodb.org/mongo-driver/bson"
+)
+
+type BusinessIndexSource2EdbReq struct {
+	EdbCode       string
+	EdbName       string
+	Frequency     string
+	Unit          string
+	ClassifyId    int
+	AdminId       int
+	AdminRealName string
+}
+
+// BusinessIndexSource2Edb 新增自有数据源到指标库
+func BusinessIndexSource2Edb(req BusinessIndexSource2EdbReq, lang string) (edb *data_manage.EdbInfo, err error, errMsg string, skip bool) {
+	if req.EdbCode == "" {
+		err = fmt.Errorf("指标ID为空")
+		return
+	}
+	defer func() {
+		if err != nil {
+			tips := fmt.Sprintf("BusinessIndexSource2Edb新增失败, Err: %s", err.Error())
+			fmt.Println(tips)
+			utils.FileLog.Info(tips)
+		}
+	}()
+	source := utils.DATA_SOURCE_BUSINESS
+
+	// 是否新增过指标
+	exist, e := data_manage.GetEdbInfoByEdbCode(source, req.EdbCode)
+	if e != nil && e.Error() != utils.ErrNoRow() {
+		err = fmt.Errorf("获取指标是否存在失败, err: %s", e.Error())
+		return
+	}
+	if exist != nil {
+		skip = true
+		return
+	}
+
+	// 开始结束时间
+	var startDate, endDate string
+
+	// 新增指标库
+	edbInfo, e, msg, _ := EdbInfoAdd(source, utils.DATA_SUB_SOURCE_EDB, req.ClassifyId, req.EdbCode, req.EdbName, req.Frequency, req.Unit, startDate, endDate, req.AdminId, req.AdminRealName, lang)
+	if e != nil {
+		errMsg = msg
+		err = fmt.Errorf("EdbInfo: 新增指标失败, err: %s", e.Error())
+		return
+	}
+
+	edb = edbInfo
+
+	return
+}
+
+// GetPageBaseBusinessIndexData
+// @Description: 获取自有数据的分页数据
+// @author: Roc
+// @datetime 2024-05-07 11:02:51
+// @param indexCode int
+// @param startSize int
+// @param pageSize int
+// @return dataCount int
+// @return dataList []*data_manage.BaseFromBusinessIndexDataItem
+// @return err error
+func GetPageBaseBusinessIndexData(indexCode string, startSize, pageSize int) (dataCount int, dataList []*data_manage.BaseFromBusinessIndexDataItem, err error) {
+	if utils.UseMongo {
+		dataCount, dataList, err = getPageBaseBusinessIndexDataByMongo(indexCode, startSize, pageSize)
+	} else {
+		dataCount, dataList, err = getPageBaseBusinessIndexDataByMysql(indexCode, startSize, pageSize)
+	}
+
+	return
+}
+
+// getPageBaseBusinessIndexDataByMongo
+// @Description: 获取自有数据的分页数据(从mongo中获取)
+// @author: Roc
+// @datetime 2024-07-01 14:01:04
+// @param indexCode string
+// @param startSize int
+// @param pageSize int
+// @return dataCount int
+// @return dataList []*data_manage.BaseFromBusinessIndexDataItem
+// @return err error
+func getPageBaseBusinessIndexDataByMongo(indexCode string, startSize, pageSize int) (dataCount int, dataList []*data_manage.BaseFromBusinessIndexDataItem, err error) {
+	dataList = make([]*data_manage.BaseFromBusinessIndexDataItem, 0)
+
+	mogDataObj := mgo.BaseFromBusinessData{}
+	// 构建查询条件
+	queryConditions := bson.M{
+		"index_code": indexCode,
+	}
+
+	// 获取数据总量
+	tmpCount, tmpErr := mogDataObj.GetCountDataList(queryConditions)
+	if tmpErr != nil && tmpErr.Error() != utils.ErrNoRow() {
+		err = tmpErr
+		return
+	}
+	dataCount = int(tmpCount)
+
+	// 获取列表数据
+	tmpDataList, tmpErr := mogDataObj.GetPageDataList(queryConditions, int64(startSize), int64(pageSize), []string{"-data_time"})
+	if tmpErr != nil {
+		err = tmpErr
+		return
+	}
+	for _, v := range tmpDataList {
+		dataList = append(dataList, &data_manage.BaseFromBusinessIndexDataItem{
+			ID:        v.ID.String(),
+			IndexCode: v.IndexCode,
+			DataTime:  v.DataTime.Format(utils.FormatDate),
+			Value:     v.Value,
+		})
+	}
+
+	return
+}
+
+// getPageBaseBusinessIndexDataByMysql
+// @Description: 获取自有数据的分页数据(从mysql中获取)
+// @author: Roc
+// @datetime 2024-07-01 14:00:41
+// @param indexCode string
+// @param startSize int
+// @param pageSize int
+// @return dataCount int
+// @return dataList []*data_manage.BaseFromBusinessIndexDataItem
+// @return err error
+func getPageBaseBusinessIndexDataByMysql(indexCode string, startSize, pageSize int) (dataCount int, dataList []*data_manage.BaseFromBusinessIndexDataItem, err error) {
+	dataList = make([]*data_manage.BaseFromBusinessIndexDataItem, 0)
+
+	businessDataObj := data_manage.BaseFromBusinessData{}
+	var condition []string
+	var pars []interface{}
+
+	condition = append(condition, "index_code = ?")
+	pars = append(pars, indexCode)
+
+	// 获取数据总量
+	tmpCount, tmpErr := businessDataObj.GetCountDataList(condition, pars)
+	if tmpErr != nil && tmpErr.Error() != utils.ErrNoRow() {
+		err = tmpErr
+		return
+	}
+	dataCount = int(tmpCount)
+
+	// 获取列表数据
+	tmpDataList, tmpErr := businessDataObj.GetPageDataList(condition, pars, " data_time desc", int64(startSize), int64(pageSize))
+	if tmpErr != nil {
+		err = tmpErr
+		return
+	}
+	for _, v := range tmpDataList {
+		dataList = append(dataList, &data_manage.BaseFromBusinessIndexDataItem{
+			ID:        fmt.Sprint(v.BusinessDataId),
+			IndexCode: v.IndexCode,
+			DataTime:  v.DataTime.Format(utils.FormatDate),
+			Value:     v.Value,
+		})
+	}
+
+	return
+}

+ 1003 - 8
services/data/chart_info.go

@@ -357,6 +357,10 @@ func GetChartEdbData(chartInfoId, chartType int, calendar, startDate, endDate st
 
 	// 特殊图形数据处理
 	switch chartType {
+	case 2: // 季节性图
+		if seasonExtraConfig != "" {
+			dataResp, err = SeasonChartData(edbList, seasonExtraConfig)
+		}
 	case 7: // 柱形图
 		barChartConf := extraConfig.(data_manage.BarChartInfoReq)
 		xEdbIdValue, yDataList, err = BarChartData(mappingList, edbDataListMap, barChartConf.DateList, barChartConf.Sort)
@@ -481,6 +485,9 @@ func getEdbDataMapList(chartInfoId, chartType int, calendar, startDate, endDate
 		var diffSeconds int64
 		if chartType == 2 { //季节性图
 			startDateReal = startDate
+			if len(mappingList) > 1 {
+				item.IsAxis = v.IsAxis
+			}
 		} else {
 			if v.EdbInfoType == 0 && v.LeadUnit != "" && v.LeadValue > 0 { //领先指标
 				var startTimeRealTemp time.Time
@@ -586,7 +593,7 @@ func getEdbDataMapList(chartInfoId, chartType int, calendar, startDate, endDate
 			}
 		}
 
-		if chartType == 2 {
+		if chartType == 2 && item.IsAxis == 1 {
 			latestDate, tmpErr := time.Parse(utils.FormatDate, v.LatestDate)
 			if tmpErr != nil {
 				//item.DataList = dataList
@@ -623,7 +630,60 @@ func getEdbDataMapList(chartInfoId, chartType int, calendar, startDate, endDate
 				}
 				item.DataList = quarterDataList
 			}
+		} else if chartType == 2 && item.IsAxis == 0 {
+			// 右轴数据处理
+			xStartDate := "01-01"
+
+			jumpYear := 0
+			var seasonExtra data_manage.SeasonExtraItem
+			if seasonExtraConfig != "" {
+				err = json.Unmarshal([]byte(seasonExtraConfig), &seasonExtra)
+				if err != nil {
+					return
+				}
+			}
+
+			if seasonExtra.XStartDate != "" {
+				xStartDate = seasonExtra.XStartDate
+				jumpYear = seasonExtra.JumpYear
+			}
+
+			length := len(dataList)
+			if length == 0 {
+				return
+			}
+			latestDate, tmpErr := time.Parse(utils.FormatDate, v.LatestDate)
+			if tmpErr != nil {
+				//item.DataList = dataList
+				item.IsNullData = true
+				edbList = append(edbList, item)
+				continue
+				err = errors.New(fmt.Sprint("获取最后实际数据的日期失败,Err:" + tmpErr.Error() + ";LatestDate:" + v.LatestDate))
+				return
+			}
+
+			var rightAxisDate time.Time
+			if jumpYear == 1 {
+				latestDate = latestDate.AddDate(-1, 0, 0)
+			}
+			latestDateStr := fmt.Sprintf("%d-%s", latestDate.Year(), xStartDate)
+			rightAxisDate, err = time.Parse(utils.FormatDate, latestDateStr)
+			if err != nil {
+				return
+			}
 
+			newDataList := make([]*data_manage.EdbDataList, 0)
+			for _, v := range dataList {
+				dataTime, e := time.Parse(utils.FormatDate, v.DataTime)
+				if e != nil {
+					err = errors.New("季节性图处理右轴指标数据转换日期失败,Err:" + e.Error())
+					return
+				}
+				if dataTime.Equal(rightAxisDate) || dataTime.After(rightAxisDate) {
+					newDataList = append(newDataList, v)
+				}
+			}
+			item.DataList = newDataList
 		} else if chartType == 7 || chartType == utils.CHART_TYPE_RADAR { //柱方图
 			//item.DataList = dataList
 		} else {
@@ -687,6 +747,7 @@ func GetSeasonEdbInfoDataListByXDate(dataList []*data_manage.EdbDataList, latest
 	}
 	endYear := lastDateT.Year()
 	nowYear := time.Now().Year()
+	chartLegendMaxYear := 0
 	dataMap := make(map[string]data_manage.QuarterXDateItem, 0)
 
 	quarterDataList := make([]*data_manage.QuarterData, 0)
@@ -732,6 +793,7 @@ func GetSeasonEdbInfoDataListByXDate(dataList []*data_manage.EdbDataList, latest
 			EndDate:   endT,
 			ShowName:  showName,
 		}
+		chartLegendMaxYear = endT.Year()
 		dataMap[name] = item
 		chartLegendMap[name] = idx
 		idx++
@@ -742,9 +804,13 @@ func GetSeasonEdbInfoDataListByXDate(dataList []*data_manage.EdbDataList, latest
 		}
 	}
 	lenYear := len(dataMap)
+	if chartLegendMaxYear > endYear {
+		chartLegendMaxYear = endYear
+	}
 	for k, v := range dataMap {
 		if i, ok := chartLegendMap[k]; ok {
-			v.ChartLegend = strconv.Itoa(endYear - lenYear + i)
+			//v.ChartLegend = strconv.Itoa(endYear - lenYear + i)
+			v.ChartLegend = strconv.Itoa(chartLegendMaxYear - lenYear + i)
 		}
 		dataMap[k] = v
 	}
@@ -795,6 +861,9 @@ func GetSeasonEdbInfoDataListByXDate(dataList []*data_manage.EdbDataList, latest
 	}
 	for k, v := range dataMap {
 		itemList := quarterMap[k]
+		/*if len(itemList) == 0 {
+			continue
+		}*/
 		quarterItem := new(data_manage.QuarterData)
 		quarterItem.Years = v.ShowName
 		quarterItem.ChartLegend = v.ChartLegend
@@ -877,6 +946,7 @@ func GetSeasonEdbInfoDataListByXDateNong(result *data_manage.EdbDataResult, late
 	}
 	endYear := lastDateT.Year()
 	nowYear := time.Now().Year()
+	chartLegendMaxYear := 0
 	dataMap := make(map[string]data_manage.QuarterXDateItem, 0)
 
 	quarterDataList := make([]*data_manage.QuarterData, 0)
@@ -921,6 +991,7 @@ func GetSeasonEdbInfoDataListByXDateNong(result *data_manage.EdbDataResult, late
 			EndDate:   endT,
 			ShowName:  showName,
 		}
+		chartLegendMaxYear = endT.Year()
 		dataMap[showName] = item
 		fmt.Println("年份" + showName + "日期" + startStr + " " + endStr)
 		startTmpT = startT
@@ -933,9 +1004,13 @@ func GetSeasonEdbInfoDataListByXDateNong(result *data_manage.EdbDataResult, late
 		}
 	}
 	lenYear := len(dataMap)
+	if chartLegendMaxYear > endYear {
+		chartLegendMaxYear = endYear
+	}
 	for k, v := range dataMap {
 		if i, ok := chartLegendMap[k]; ok {
-			v.ChartLegend = strconv.Itoa(endYear - lenYear + i)
+			//v.ChartLegend = strconv.Itoa(endYear - lenYear + i)
+			v.ChartLegend = strconv.Itoa(chartLegendMaxYear - lenYear + i)
 		}
 		dataMap[k] = v
 	}
@@ -1012,6 +1087,9 @@ func GetSeasonEdbInfoDataListByXDateNong(result *data_manage.EdbDataResult, late
 
 	for k, v := range dataMap {
 		itemList := quarterMap[k]
+		/*if len(itemList) == 0 {
+			continue
+		}*/
 		quarterItem := new(data_manage.QuarterData)
 		quarterItem.Years = v.ShowName
 		quarterItem.ChartLegend = v.ChartLegend
@@ -2753,7 +2831,7 @@ func RadarChartData(mappingList []*data_manage.ChartEdbInfoMapping, edbDataListM
 }
 
 // GetChartConvertEdbData 获取图表数据转换的指标数据
-func GetChartConvertEdbData(chartInfoId, chartType int, calendar, startDate, endDate string, mappingList []*data_manage.ChartEdbInfoMapping, extraConfigStr string, seasonExtraConfig string) (edbList []*data_manage.ChartEdbInfoMapping, xEdbIdValue []int, yDataList []data_manage.YData, dataResp interface{}, err error, errMsg string) {
+func GetChartConvertEdbData(chartInfoId, chartType int, calendar, startDate, endDate string, mappingList []*data_manage.ChartEdbInfoMapping, extraConfigStr string, seasonExtraConfig string, isAxis int) (edbList []*data_manage.ChartEdbInfoMapping, xEdbIdValue []int, yDataList []data_manage.YData, dataResp interface{}, err error, errMsg string) {
 	edbList = make([]*data_manage.ChartEdbInfoMapping, 0)
 	xEdbIdValue = make([]int, 0)
 	yDataList = make([]data_manage.YData, 0)
@@ -2809,13 +2887,17 @@ func GetChartConvertEdbData(chartInfoId, chartType int, calendar, startDate, end
 	}
 
 	// 指标对应的所有数据
-	edbDataListMap, edbList, err := getEdbConvertDataMapList(chartInfoId, chartType, calendar, startDate, endDate, mappingList, seasonExtraConfig)
+	edbDataListMap, edbList, err := getEdbConvertDataMapList(chartInfoId, chartType, calendar, startDate, endDate, mappingList, seasonExtraConfig, isAxis)
 	if err != nil {
 		return
 	}
 
 	// 特殊图形数据处理
 	switch chartType {
+	case 2: // 季节性图
+		if seasonExtraConfig != "" {
+			dataResp, err = SeasonChartData(edbList, seasonExtraConfig)
+		}
 	case 7: // 柱形图
 		barChartConf := extraConfig.(data_manage.BarChartInfoReq)
 		xEdbIdValue, yDataList, err = BarChartData(mappingList, edbDataListMap, barChartConf.DateList, barChartConf.Sort)
@@ -2863,7 +2945,7 @@ func GetChartConvertEdbData(chartInfoId, chartType int, calendar, startDate, end
 	return
 }
 
-func getEdbConvertDataMapList(chartInfoId, chartType int, calendar, startDate, endDate string, mappingList []*data_manage.ChartEdbInfoMapping, seasonExtraConfig string) (edbDataListMap map[int][]*data_manage.EdbDataList, edbList []*data_manage.ChartEdbInfoMapping, err error) {
+func getEdbConvertDataMapList(chartInfoId, chartType int, calendar, startDate, endDate string, mappingList []*data_manage.ChartEdbInfoMapping, seasonExtraConfig string, isAxis int) (edbDataListMap map[int][]*data_manage.EdbDataList, edbList []*data_manage.ChartEdbInfoMapping, err error) {
 	// 指标对应的所有数据
 	edbDataListMap = make(map[int][]*data_manage.EdbDataList)
 
@@ -2932,6 +3014,9 @@ func getEdbConvertDataMapList(chartInfoId, chartType int, calendar, startDate, e
 		var diffSeconds int64
 		if chartType == 2 { //季节性图
 			startDateReal = startDate
+			if len(mappingList) > 1 {
+				item.IsAxis = v.IsAxis
+			}
 		} else {
 			if v.EdbInfoType == 0 && v.LeadUnit != "" && v.LeadValue > 0 { //领先指标
 				var startTimeRealTemp time.Time
@@ -3033,7 +3118,7 @@ func getEdbConvertDataMapList(chartInfoId, chartType int, calendar, startDate, e
 			}
 		}
 
-		if chartType == 2 {
+		if chartType == 2 && isAxis == 1 {
 			latestDate, tmpErr := time.Parse(utils.FormatDate, v.LatestDate)
 			if tmpErr != nil {
 				//item.DataList = dataList
@@ -3070,7 +3155,29 @@ func getEdbConvertDataMapList(chartInfoId, chartType int, calendar, startDate, e
 				}
 				item.DataList = quarterDataList
 			}
-
+		} else if chartType == 2 && isAxis == 0 {
+			// 右轴数据处理,只要最新一年
+			latestDate, tmpErr := time.Parse(utils.FormatDate, v.LatestDate)
+			if tmpErr != nil {
+				//item.DataList = dataList
+				item.IsNullData = true
+				edbList = append(edbList, item)
+				continue
+				err = errors.New(fmt.Sprint("获取最后实际数据的日期失败,Err:" + tmpErr.Error() + ";LatestDate:" + v.LatestDate))
+				return
+			}
+			newDataList := make([]*data_manage.EdbDataList, 0)
+			for _, v := range dataList {
+				dataTime, e := time.Parse(utils.FormatDate, v.DataTime)
+				if e != nil {
+					err = errors.New("季节性图处理右轴指标数据转换日期失败,Err:" + e.Error())
+					return
+				}
+				if dataTime.Year() == latestDate.Year() {
+					newDataList = append(newDataList, v)
+				}
+			}
+			item.DataList = newDataList
 		} else if chartType == 7 || chartType == utils.CHART_TYPE_RADAR { //柱方图
 			//item.DataList = dataList
 		} else {
@@ -3081,3 +3188,891 @@ func getEdbConvertDataMapList(chartInfoId, chartType int, calendar, startDate, e
 
 	return
 }
+
+// GetChartEdbDataV2 获取图表的指标数据
+func GetChartEdbDataV2(chartInfoId, chartType int, calendar, startDate, endDate string, mappingList []*data_manage.ChartEdbInfoMapping, extraConfigStr string, seasonExtraConfig string, chartInfoData ChartInfoDataShow) (edbList []*data_manage.ChartEdbInfoMapping, xEdbIdValue []int, yDataList []data_manage.YData, dataResp interface{}, err error, errMsg string) {
+	edbList = make([]*data_manage.ChartEdbInfoMapping, 0)
+	xEdbIdValue = make([]int, 0)
+	yDataList = make([]data_manage.YData, 0)
+
+	var extraConfig interface{}
+	switch chartType {
+	case 7: // 柱形图
+		var barConfig data_manage.BarChartInfoReq
+		if extraConfigStr == `` {
+			errMsg = "柱方图未配置"
+			err = errors.New(errMsg)
+			return
+		}
+		err = json.Unmarshal([]byte(extraConfigStr), &barConfig)
+		if err != nil {
+			errMsg = "柱方图配置异常"
+			err = errors.New(errMsg)
+			return
+		}
+		extraConfig = barConfig
+	case 10: // 截面散点图
+		var tmpExtraConfig data_manage.SectionScatterReq
+		if extraConfigStr == `` {
+			errMsg = "截面散点图未配置"
+			err = errors.New(errMsg)
+			return
+		}
+		err = json.Unmarshal([]byte(extraConfigStr), &tmpExtraConfig)
+		if err != nil {
+			errMsg = "截面散点配置异常"
+			err = errors.New(errMsg)
+			return
+		}
+
+		extraConfig = tmpExtraConfig
+	case utils.CHART_TYPE_RADAR:
+		var barConfig data_manage.RadarChartInfoReq
+		if extraConfigStr == `` {
+			errMsg = "雷达图未配置"
+			err = errors.New(errMsg)
+			return
+		}
+		err = json.Unmarshal([]byte(extraConfigStr), &barConfig)
+		if err != nil {
+			errMsg = "雷达图配置异常"
+			err = errors.New(errMsg)
+			return
+		}
+		extraConfig = barConfig
+	default:
+		xEdbIdValue = make([]int, 0)
+		yDataList = make([]data_manage.YData, 0)
+	}
+
+	// 指标对应的所有数据
+	edbDataListMap, edbList, err := chartInfoData.GetEdbDataMapList(chartInfoId, chartType, calendar, startDate, endDate, mappingList, seasonExtraConfig)
+	if err != nil {
+		return
+	}
+
+	// 特殊图形数据处理
+	switch chartType {
+	case 2: // 季节性图
+		if seasonExtraConfig != "" {
+			dataResp, err = SeasonChartData(edbList, seasonExtraConfig)
+		}
+	case 7: // 柱形图
+		barChartConf := extraConfig.(data_manage.BarChartInfoReq)
+		xEdbIdValue, yDataList, err = BarChartData(mappingList, edbDataListMap, barChartConf.DateList, barChartConf.Sort)
+
+		for k := range yDataList {
+			yDataList[k].Unit = barChartConf.Unit
+			yDataList[k].UnitEn = barChartConf.UnitEn
+		}
+
+		for _, v := range edbList {
+			// 指标别名
+			if barChartConf.EdbInfoIdList != nil && len(barChartConf.EdbInfoIdList) > 0 {
+				for _, reqEdb := range barChartConf.EdbInfoIdList {
+					if v.EdbInfoId == reqEdb.EdbInfoId {
+						v.EdbAliasName = reqEdb.Name
+					}
+				}
+			}
+		}
+	case 10: // 截面散点图
+		sectionScatterConf := extraConfig.(data_manage.SectionScatterReq)
+		xEdbIdValue, dataResp, err = GetSectionScatterChartData(chartInfoId, mappingList, edbDataListMap, sectionScatterConf)
+
+		var tmpExtraConfig data_manage.SectionScatterReq
+		if extraConfigStr == `` {
+			errMsg = "截面散点图未配置"
+			err = errors.New(errMsg)
+			return
+		}
+		err = json.Unmarshal([]byte(extraConfigStr), &tmpExtraConfig)
+		if err != nil {
+			errMsg = "截面散点配置异常"
+			err = errors.New(errMsg)
+			return
+		}
+
+		// 这个数据没有必要返回给前端
+		for _, v := range edbList {
+			v.DataList = nil
+		}
+	case utils.CHART_TYPE_RADAR: //雷达图
+		radarConf := extraConfig.(data_manage.RadarChartInfoReq)
+		xEdbIdValue, dataResp, err = RadarChartData(mappingList, edbDataListMap, radarConf)
+	}
+	return
+}
+
+
+// SeasonChartData 季节性图的数据处理
+func SeasonChartData(dataList []*data_manage.ChartEdbInfoMapping, seasonExtraConfig string) (dataResp data_manage.SeasonChartResp, err error) {
+	var seasonConfig data_manage.SeasonExtraItem
+	err = json.Unmarshal([]byte(seasonExtraConfig), &seasonConfig)
+	if err != nil {
+		err = errors.New("季节性图配置异常, Err:" + err.Error())
+		return
+	}
+
+	for _, mappingItem := range dataList {
+		if mappingItem.IsAxis == 0 {
+			continue
+		}
+		quarterDataList := mappingItem.DataList.(data_manage.QuarterDataList)
+		// 上下限区间
+		if seasonConfig.MaxMinLimits.Year > 0 {
+			dataResp.MaxMinLimits.List = make([]*data_manage.MaxMinLimitsData, 0)
+			dataTimeMap := make(map[time.Time]time.Time)
+			dataTimeList := make([]string, 0)
+			maxValueMap := make(map[time.Time]float64)
+			minValueMap := make(map[time.Time]float64)
+
+			maxMinDataList := make([]*data_manage.MaxMinLimitsData, 0)
+			// 日度 周度插值
+			for _, v := range quarterDataList {
+				if mappingItem.Frequency == "日度" || mappingItem.Frequency == "周度" {
+					handleDataMap := make(map[string]float64)
+					dataTimeList, _, err = HandleDataByLinearRegressionToList(v.DataList, handleDataMap)
+					if err != nil {
+						err = errors.New("插值处理数据异常, Err:" + err.Error())
+						return
+					}
+					for _, date := range dataTimeList {
+						dateTime, e := time.Parse(utils.FormatDate, date)
+						if e != nil {
+							err = errors.New("时间格式化异常, Err:" + e.Error())
+							return
+						}
+						// 不包含今年
+						if dateTime.Year() == time.Now().Year() {
+							continue
+						}
+						newDate := dateTime.AddDate(time.Now().Year()-dateTime.Year(), 0, 0)
+						// 处理上下限列表
+						if value, ok := maxValueMap[newDate]; ok {
+							if value < handleDataMap[date] {
+								maxValueMap[newDate] = handleDataMap[date]
+							}
+						} else {
+							maxValueMap[newDate] = handleDataMap[date]
+						}
+
+						if value, ok := minValueMap[newDate]; ok {
+							if value > handleDataMap[date] {
+								minValueMap[newDate] = handleDataMap[date]
+							}
+						} else {
+							minValueMap[newDate] = handleDataMap[date]
+						}
+
+						dataTimeMap[newDate] = newDate
+					}
+				} else {
+					// 旬度、月度、季度、半年度 不插值,需要先把日期列表和数据map取出来
+					for _, vv := range v.DataList {
+						dateTime, e := time.Parse(utils.FormatDate, vv.DataTime)
+						if e != nil {
+							err = errors.New("时间格式化异常, Err:" + e.Error())
+							return
+						}
+						// 不包含今年
+						if dateTime.Year() == time.Now().Year() {
+							continue
+						}
+						newDate := dateTime.AddDate(time.Now().Year()-dateTime.Year(), 0, 0)
+
+						if value, ok := maxValueMap[newDate]; ok {
+							if value < vv.Value {
+								maxValueMap[newDate] = vv.Value
+							}
+						} else {
+							maxValueMap[newDate] = vv.Value
+						}
+
+						if value, ok := minValueMap[newDate]; ok {
+							if value > vv.Value {
+								minValueMap[newDate] = vv.Value
+							}
+						} else {
+							minValueMap[newDate] = vv.Value
+						}
+						dataTimeMap[newDate] = newDate
+					}
+				}
+			}
+
+			for _, v := range dataTimeMap {
+				maxMinItem := &data_manage.MaxMinLimitsData{}
+				if maxValue, ok := maxValueMap[v]; ok {
+					maxMinItem.MaxValue = maxValue
+				} else {
+					maxMinItem.MaxValue = minValueMap[v]
+				}
+
+				if minValue, ok := minValueMap[v]; ok {
+					maxMinItem.MinValue = minValue
+				} else {
+					maxMinItem.MinValue = maxValueMap[v]
+				}
+				maxMinItem.DataTime = v.Format(utils.FormatDate)
+				maxMinItem.DataTimestamp = v.UnixNano() / 1e6
+
+				maxMinDataList = append(maxMinDataList, maxMinItem)
+
+			}
+
+			// 排序
+			sort.Slice(maxMinDataList, func(i, j int) bool {
+				return maxMinDataList[i].DataTime < maxMinDataList[j].DataTime
+			})
+
+			dataResp.MaxMinLimits.List = maxMinDataList
+			dataResp.MaxMinLimits.Color = seasonConfig.MaxMinLimits.Color
+			dataResp.MaxMinLimits.Legend = seasonConfig.MaxMinLimits.Legend
+			dataResp.MaxMinLimits.IsShow = seasonConfig.MaxMinLimits.IsShow
+			dataResp.MaxMinLimits.IsAdd = seasonConfig.MaxMinLimits.IsAdd
+			dataResp.MaxMinLimits.Year = seasonConfig.MaxMinLimits.Year
+		}
+
+		// 自定义同期均线
+		if seasonConfig.SamePeriodAverage.Year > 0 {
+			handleDataMap := make(map[string]float64)
+			dataTimeMap := make(map[time.Time]time.Time)
+			dataTimeList := make([]string, 0)
+			valueMap := make(map[time.Time]float64)
+
+			averageDataList := make([]*data_manage.SamePeriodAverageData, 0)
+			for i := len(quarterDataList) - 1; i > len(quarterDataList)-seasonConfig.SamePeriodAverage.Year && i > 0; i-- {
+				// 插值成日度
+				dataTimeList, _, err = HandleDataByLinearRegressionToList(quarterDataList[i].DataList, handleDataMap)
+				if err != nil {
+					err = errors.New("插值处理数据异常, Err:" + err.Error())
+					return
+				}
+				for _, date := range dataTimeList {
+					dateTime, e := time.Parse(utils.FormatDate, date)
+					if e != nil {
+						err = errors.New("时间格式化异常, Err:" + e.Error())
+						return
+					}
+					newDate := dateTime.AddDate(time.Now().Year()-dateTime.Year(), 0, 0)
+					// 处理均值
+					if value, ok := valueMap[newDate]; ok {
+						valueMap[newDate] = (handleDataMap[date] + value) / 2
+					} else {
+						valueMap[newDate] = handleDataMap[date]
+					}
+
+					dataTimeMap[newDate] = newDate
+				}
+			}
+
+			for _, v := range dataTimeMap {
+				averageItem := &data_manage.SamePeriodAverageData{}
+				if value, ok := valueMap[v]; ok {
+					averageItem.Value = value
+				}
+				averageItem.DataTime = v.Format(utils.FormatDate)
+				averageItem.DataTimestamp = v.UnixNano() / 1e6
+
+				averageDataList = append(averageDataList, averageItem)
+
+			}
+
+			// 排序
+			sort.Slice(averageDataList, func(i, j int) bool {
+				return averageDataList[i].DataTime < averageDataList[j].DataTime
+			})
+
+			dataResp.SamePeriodAverage.List = averageDataList
+			dataResp.SamePeriodAverage.Year = seasonConfig.SamePeriodAverage.Year
+			dataResp.SamePeriodAverage.Color = seasonConfig.SamePeriodAverage.Color
+			dataResp.SamePeriodAverage.Legend = seasonConfig.SamePeriodAverage.Legend
+			dataResp.SamePeriodAverage.IsShow = seasonConfig.SamePeriodAverage.IsShow
+			dataResp.SamePeriodAverage.LineType = seasonConfig.SamePeriodAverage.LineType
+			dataResp.SamePeriodAverage.LineWidth = seasonConfig.SamePeriodAverage.LineWidth
+			dataResp.SamePeriodAverage.IsAdd = seasonConfig.SamePeriodAverage.IsAdd
+
+		}
+
+		// 自定义同期标准差
+		if seasonConfig.SamePeriodStandardDeviation.Year > 1 && seasonConfig.SamePeriodStandardDeviation.Multiple > 0 {
+			// 先算均值,再算标准差
+			handleDataMap := make(map[string]float64)
+			dataTimeMap := make(map[time.Time]time.Time)
+			dataTimeValueMap := make(map[time.Time][]float64)
+			dataTimeList := make([]string, 0)
+			valueMap := make(map[time.Time]float64)
+
+			samePeriodStandardDeviationList := make([]*data_manage.MaxMinLimitsData, 0)
+			for i := len(quarterDataList) - 1; i > len(quarterDataList)-seasonConfig.SamePeriodAverage.Year-1 && i > 0; i-- {
+				// 插值成日度
+				dataTimeList, _, err = HandleDataByLinearRegressionToListV2(quarterDataList[i].DataList, handleDataMap)
+				if err != nil {
+					err = errors.New("插值处理数据异常, Err:" + err.Error())
+					return
+				}
+				for _, date := range dataTimeList {
+					dateTime, e := time.Parse(utils.FormatDate, date)
+					if e != nil {
+						err = errors.New("时间格式化异常, Err:" + e.Error())
+						return
+					}
+					newDate := dateTime.AddDate(time.Now().Year()-dateTime.Year(), 0, 0)
+					// 处理均值
+					if value, ok := valueMap[newDate]; ok {
+						valueMap[newDate] = (handleDataMap[date] + value) / 2
+					} else {
+						valueMap[newDate] = handleDataMap[date]
+					}
+
+					dataTimeMap[newDate] = newDate
+					valueList := dataTimeValueMap[newDate]
+					valueList = append(valueList, handleDataMap[date])
+					dataTimeValueMap[newDate] = valueList
+				}
+			}
+
+			for _, v := range dataTimeMap {
+				valueList := dataTimeValueMap[v]
+				stdev := utils.CalculateStandardDeviation(valueList)
+				stdev, _ = decimal.NewFromFloat(stdev).Round(4).Float64()
+
+				maxMinItem := &data_manage.MaxMinLimitsData{}
+
+				if value, ok := valueMap[v]; ok {
+					maxMinItem.MaxValue = value + stdev*seasonConfig.SamePeriodStandardDeviation.Multiple
+					maxMinItem.MinValue = value - stdev*seasonConfig.SamePeriodStandardDeviation.Multiple
+				}
+
+				maxMinItem.DataTime = v.Format(utils.FormatDate)
+				maxMinItem.DataTimestamp = v.UnixNano() / 1e6
+
+				samePeriodStandardDeviationList = append(samePeriodStandardDeviationList, maxMinItem)
+
+			}
+
+			// 排序
+			sort.Slice(samePeriodStandardDeviationList, func(i, j int) bool {
+				return samePeriodStandardDeviationList[i].DataTime < samePeriodStandardDeviationList[j].DataTime
+			})
+
+			dataResp.SamePeriodStandardDeviation.List = samePeriodStandardDeviationList
+			dataResp.SamePeriodStandardDeviation.Color = seasonConfig.SamePeriodStandardDeviation.Color
+			dataResp.SamePeriodStandardDeviation.Legend = seasonConfig.SamePeriodStandardDeviation.Legend
+			dataResp.SamePeriodStandardDeviation.IsShow = seasonConfig.SamePeriodStandardDeviation.IsShow
+			dataResp.SamePeriodStandardDeviation.Multiple = seasonConfig.SamePeriodStandardDeviation.Multiple
+			dataResp.SamePeriodStandardDeviation.Year = seasonConfig.SamePeriodStandardDeviation.Year
+			dataResp.SamePeriodStandardDeviation.IsAdd = seasonConfig.SamePeriodStandardDeviation.IsAdd
+		}
+
+		// 自定义右轴
+		if seasonConfig.RightAxis.IndicatorType != 0 {
+			if seasonConfig.RightAxis.IndicatorType == 1 {
+				startTime, _ := time.Parse(utils.FormatDate, mappingItem.StartDate)
+				for i := len(quarterDataList) - 1; i > len(quarterDataList)-2 && i > 0; i-- {
+					var rightMappingItem data_manage.ChartEdbInfoMapping
+					rightMappingItem = *mappingItem
+					// 计算同比值
+					tbzDataList, minValue, maxValue, e := GetEdbDataTbzForSeason(mappingItem.Frequency, quarterDataList[i].DataList, startTime)
+					if e != nil {
+						err = errors.New("计算同比值失败, Err:" + e.Error())
+						return
+					}
+					rightMappingItem.DataList = tbzDataList
+					rightMappingItem.MaxData = maxValue
+					rightMappingItem.MinData = minValue
+					dataResp.RightAxis.EdbInfoList = append(dataResp.RightAxis.EdbInfoList, &rightMappingItem)
+				}
+			}
+			dataResp.RightAxis.SeasonRightAxis = seasonConfig.RightAxis
+		}
+	}
+
+	return
+}
+
+// 计算百分位对应的值
+func PercentileAlgorithm(x float64, data []float64) float64 {
+	N := float64(len(data))
+	n := (x / 100) * (N - 1)
+
+	// 如果n是整数,则直接返回第n个数值
+	if n == float64(int(n)) {
+		return data[int(n)-1]
+	}
+
+	// 如果n是小数,执行插值
+	nInt := int(n)
+	e := n - float64(nInt)
+
+	// 取出相邻的两个数值
+	Sn := data[nInt-1]
+	Sn1 := data[nInt]
+
+	// 计算插值结果
+	y := Sn + e*(Sn1-Sn)
+
+	return y
+}
+
+func MarkerLineCalculate(markerLine data_manage.MarkersLine, dataList interface{}, chartInfo *data_manage.ChartInfoView) (value string, err error) {
+	if markerLine.Calculation == 1 {
+		// 区间均值
+		averge := 0.0
+		length := 0
+		// 计算左轴
+		if chartInfo.ChartType == 2 && markerLine.EdbType == 0 {
+			//季节性图结构体不一样
+			quarterDataList := dataList.(data_manage.QuarterDataList)
+			for _, quarterData := range quarterDataList[len(quarterDataList)-1:] {
+				for _, vv := range quarterData.DataList {
+					if markerLine.TimeIntervalType == 1 {
+						startDate := markerLine.StartDate.Date
+						endDate := time.Now().Format(utils.FormatDate)
+						if markerLine.StartDate.TimeType == 2 {
+							// 动态
+							if markerLine.StartDate.Conf.BaseDate == 1 {
+								// 指标最新日期
+								startDate = quarterData.DataList[len(quarterData.DataList)-1].DataTime
+							} else {
+								// 系统日期
+								startDate = time.Now().Format(utils.FormatDate)
+							}
+							startDate, err = HandleDateChange(startDate, markerLine.StartDate.Conf)
+						}
+						if markerLine.EndDate.TimeType == 1 {
+							// 固定
+							endDate = markerLine.EndDate.Date
+						} else if markerLine.EndDate.TimeType == 2 {
+							// 动态
+							if markerLine.StartDate.Conf.BaseDate == 1 {
+								// 指标最新日期
+								endDate = quarterData.DataList[len(quarterData.DataList)-1].DataTime
+							} else {
+								// 系统日期
+								endDate = time.Now().Format(utils.FormatDate)
+							}
+							endDate, err = HandleDateChange(endDate, markerLine.StartDate.Conf)
+						}
+						if vv.DataTime >= startDate && vv.DataTime <= endDate {
+							averge += vv.Value
+							length +=1
+						}
+					} else {
+						averge += vv.Value
+						length +=1
+					}
+				}
+				averge = averge / float64(length)
+				value = fmt.Sprintf("%.2f", averge)
+			}
+		} else {
+			dataList := dataList.([]*data_manage.EdbDataList)
+			for _, dataItem := range dataList {
+				if markerLine.TimeIntervalType == 1 {
+					startDate := markerLine.StartDate.Date
+					endDate := time.Now().Format(utils.FormatDate)
+					if markerLine.StartDate.TimeType == 2 {
+						// 动态
+						if markerLine.StartDate.Conf.BaseDate == 1 {
+							// 指标最新日期
+							startDate = dataList[len(dataList)-1].DataTime
+						} else {
+							// 系统日期
+							startDate = time.Now().Format(utils.FormatDate)
+						}
+						startDate, err = HandleDateChange(startDate, markerLine.StartDate.Conf)
+					}
+					if markerLine.EndDate.TimeType == 1 {
+						// 固定
+						endDate = markerLine.EndDate.Date
+					} else if markerLine.EndDate.TimeType == 2 {
+						// 动态
+						if markerLine.StartDate.Conf.BaseDate == 1 {
+							// 指标最新日期
+							endDate = dataList[len(dataList)-1].DataTime
+						} else {
+							// 系统日期
+							endDate = time.Now().Format(utils.FormatDate)
+						}
+						endDate, err = HandleDateChange(endDate, markerLine.StartDate.Conf)
+					}
+					if dataItem.DataTime >= startDate && dataItem.DataTime <= endDate {
+						averge += dataItem.Value
+						length += 1
+					}
+				} else {
+					averge += dataItem.Value
+					length += 1
+				}
+			}
+			averge = averge / float64(length)
+
+			value = fmt.Sprintf("%.2f", averge)
+		}
+	} else if markerLine.Calculation == 2 {
+		// 区间均值加N倍标准差
+		averge := 0.0
+		length := 0
+		// 计算左轴
+		if chartInfo.ChartType == 2 && markerLine.EdbType == 0 {
+			//季节性图结构体不一样
+			faloatList := make([]float64, 0)
+			quarterDataList := dataList.(data_manage.QuarterDataList)
+			for _, quarterData := range quarterDataList[len(quarterDataList)-1:] {
+				for _, vv := range quarterData.DataList {
+					if markerLine.TimeIntervalType == 1 {
+						startDate := markerLine.StartDate.Date
+						endDate := time.Now().Format(utils.FormatDate)
+						if markerLine.StartDate.TimeType == 2 {
+							// 动态
+							if markerLine.StartDate.Conf.BaseDate == 1 {
+								// 指标最新日期
+								startDate = quarterData.DataList[len(quarterData.DataList)-1].DataTime
+							} else {
+								// 系统日期
+								startDate = time.Now().Format(utils.FormatDate)
+							}
+							startDate, err = HandleDateChange(startDate, markerLine.StartDate.Conf)
+						}
+						if markerLine.EndDate.TimeType == 1 {
+							// 固定
+							endDate = markerLine.EndDate.Date
+						} else if markerLine.EndDate.TimeType == 2 {
+							// 动态
+							if markerLine.StartDate.Conf.BaseDate == 1 {
+								// 指标最新日期
+								endDate = quarterData.DataList[len(quarterData.DataList)-1].DataTime
+							} else {
+								// 系统日期
+								endDate = time.Now().Format(utils.FormatDate)
+							}
+							endDate, err = HandleDateChange(endDate, markerLine.StartDate.Conf)
+						}
+						if vv.DataTime >= startDate && vv.DataTime <= endDate {
+							faloatList = append(faloatList, vv.Value)
+							averge += vv.Value
+							length += 1
+						}
+					} else {
+						faloatList = append(faloatList, vv.Value)
+						averge += vv.Value
+						length += 1
+					}
+				}
+				averge = averge / float64(length)
+				stdev := utils.CalculateStandardDeviation(faloatList)
+				stdev, _ = decimal.NewFromFloat(stdev).Round(4).Float64()
+
+				value = fmt.Sprintf("%.2f", averge+stdev*markerLine.CalculationValue)
+			}
+
+		} else {
+			dataList := dataList.([]*data_manage.EdbDataList)
+			floatList := make([]float64, 0)
+			for _, dataItem := range dataList {
+				if markerLine.TimeIntervalType == 1 {
+					startDate := markerLine.StartDate.Date
+					endDate := time.Now().Format(utils.FormatDate)
+					if markerLine.StartDate.TimeType == 2 {
+						// 动态
+						if markerLine.StartDate.Conf.BaseDate == 1 {
+							// 指标最新日期
+							startDate = dataList[len(dataList)-1].DataTime
+						} else {
+							// 系统日期
+							startDate = time.Now().Format(utils.FormatDate)
+						}
+						startDate, err = HandleDateChange(startDate, markerLine.StartDate.Conf)
+					}
+					if markerLine.EndDate.TimeType == 1 {
+						// 固定
+						endDate = markerLine.EndDate.Date
+					} else if markerLine.EndDate.TimeType == 2 {
+						// 动态
+						if markerLine.StartDate.Conf.BaseDate == 1 {
+							// 指标最新日期
+							endDate = dataList[len(dataList)-1].DataTime
+						} else {
+							// 系统日期
+							endDate = time.Now().Format(utils.FormatDate)
+						}
+						endDate, err = HandleDateChange(endDate, markerLine.StartDate.Conf)
+					}
+					if dataItem.DataTime >= startDate && dataItem.DataTime <= endDate {
+						floatList = append(floatList, dataItem.Value)
+						averge += dataItem.Value
+						length += 1
+					}
+				} else {
+					floatList = append(floatList, dataItem.Value)
+					averge += dataItem.Value
+					length += 1
+				}
+			}
+			averge = averge / float64(length)
+
+			stdev := utils.CalculateStandardDeviation(floatList)
+			stdev, _ = decimal.NewFromFloat(stdev).Round(4).Float64()
+
+			value = fmt.Sprintf("%.2f", averge+stdev*markerLine.CalculationValue)
+		}
+	} else if markerLine.Calculation == 3 {
+		// 区间个数分位
+		markerLineValue := 0.0
+		if chartInfo.ChartType == 2 && markerLine.EdbType == 0 {
+			//季节性图结构体不一样
+			faloatList := make([]float64, 0)
+			quarterDataList := dataList.(data_manage.QuarterDataList)
+			for _, quarterData := range quarterDataList[len(quarterDataList)-1:] {
+				for _, vv := range quarterData.DataList {
+					if markerLine.TimeIntervalType == 1 {
+						startDate := markerLine.StartDate.Date
+						endDate := time.Now().Format(utils.FormatDate)
+						if markerLine.StartDate.TimeType == 2 {
+							// 动态
+							if markerLine.StartDate.Conf.BaseDate == 1 {
+								// 指标最新日期
+								startDate = quarterData.DataList[len(quarterData.DataList)-1].DataTime
+							} else {
+								// 系统日期
+								startDate = time.Now().Format(utils.FormatDate)
+							}
+							startDate, err = HandleDateChange(startDate, markerLine.StartDate.Conf)
+						}
+						if markerLine.EndDate.TimeType == 1 {
+							// 固定
+							endDate = markerLine.EndDate.Date
+						} else if markerLine.EndDate.TimeType == 2 {
+							// 动态
+							if markerLine.StartDate.Conf.BaseDate == 1 {
+								// 指标最新日期
+								endDate = quarterData.DataList[len(quarterData.DataList)-1].DataTime
+							} else {
+								// 系统日期
+								endDate = time.Now().Format(utils.FormatDate)
+							}
+							endDate, err = HandleDateChange(endDate, markerLine.StartDate.Conf)
+						}
+						if vv.DataTime >= startDate && vv.DataTime <= endDate {
+							faloatList = append(faloatList, vv.Value)
+						}
+					} else {
+						faloatList = append(faloatList, vv.Value)
+					}
+				}
+
+				markerLineValue = PercentileAlgorithm(markerLine.CalculationValue, faloatList)
+				value = fmt.Sprintf("%.2f", markerLineValue)
+			}
+
+		} else {
+			dataList := dataList.([]*data_manage.EdbDataList)
+			floatList := make([]float64, 0)
+			for _, dataItem := range dataList {
+				if markerLine.TimeIntervalType == 1 {
+					startDate := markerLine.StartDate.Date
+					endDate := time.Now().Format(utils.FormatDate)
+					if markerLine.StartDate.TimeType == 2 {
+						// 动态
+						if markerLine.StartDate.Conf.BaseDate == 1 {
+							// 指标最新日期
+							startDate = dataList[len(dataList)-1].DataTime
+						} else {
+							// 系统日期
+							startDate = time.Now().Format(utils.FormatDate)
+						}
+						startDate, err = HandleDateChange(startDate, markerLine.StartDate.Conf)
+					}
+					if markerLine.EndDate.TimeType == 1 {
+						// 固定
+						endDate = markerLine.EndDate.Date
+					} else if markerLine.EndDate.TimeType == 2 {
+						// 动态
+						if markerLine.StartDate.Conf.BaseDate == 1 {
+							// 指标最新日期
+							endDate = dataList[len(dataList)-1].DataTime
+						} else {
+							// 系统日期
+							endDate = time.Now().Format(utils.FormatDate)
+						}
+						endDate, err = HandleDateChange(endDate, markerLine.StartDate.Conf)
+					}
+					if dataItem.DataTime >= startDate && dataItem.DataTime <= endDate {
+						floatList = append(floatList, dataItem.Value)
+					}
+				} else {
+					floatList = append(floatList, dataItem.Value)
+				}
+			}
+
+			markerLineValue = PercentileAlgorithm(markerLine.CalculationValue, floatList)
+			value = fmt.Sprintf("%.2f", markerLineValue)
+		}
+	}
+	return
+}
+
+// HandleDateChange 处理日期变换
+func HandleDateChange(date string, edbDateConf data_manage.EdbDateChangeConf) (newDate string, err error) {
+	newDate = date
+	if newDate != "" {
+		if len(edbDateConf.DateChange) > 0 {
+			var dateTime time.Time
+			dateTime, err = time.ParseInLocation(utils.FormatDate, newDate, time.Local)
+			if err != nil {
+				err = fmt.Errorf("日期解析失败: %s", err.Error())
+				return
+			}
+			for _, v := range edbDateConf.DateChange {
+				if v.ChangeType == 1 {
+					dateTime = dateTime.AddDate(v.Year, v.Month, v.Day)
+					newDate = dateTime.Format(utils.FormatDate)
+				} else if v.ChangeType == 2 {
+					newDate, err, _ = handleSystemAppointDateT2(dateTime, v.FrequencyDay, v.Frequency)
+					if err != nil {
+						return
+					}
+					dateTime, err = time.ParseInLocation(utils.FormatDate, newDate, time.Local)
+					if err != nil {
+						err = fmt.Errorf("日期解析失败: %s", err.Error())
+						return
+					}
+				}
+			}
+		}
+	}
+
+	return
+}
+
+
+// handleSystemAppointDateT
+// @Description: 处理系统日期相关的指定频率(所在周/旬/月/季/半年/年的最后/最早一天)
+// @author: Roc
+// @datetime2023-10-27 09:31:35
+// @param Frequency string
+// @param Day string
+// @return date string
+// @return err error
+// @return errMsg string
+func handleSystemAppointDateT2(currDate time.Time, appointDay, frequency string) (date string, err error, errMsg string) {
+	//currDate := time.Now()
+	switch frequency {
+	case "本周":
+		day := int(currDate.Weekday())
+		if day == 0 { // 周日
+			day = 7
+		}
+		num := 0
+		switch appointDay {
+		case "周一":
+			num = 1
+		case "周二":
+			num = 2
+		case "周三":
+			num = 3
+		case "周四":
+			num = 4
+		case "周五":
+			num = 5
+		case "周六":
+			num = 6
+		case "周日":
+			num = 7
+		}
+		day = num - day
+		date = currDate.AddDate(0, 0, day).Format(utils.FormatDate)
+	case "本旬":
+		day := currDate.Day()
+		var tmpDate time.Time
+		switch appointDay {
+		case "第一天":
+			if day <= 10 {
+				tmpDate = time.Date(currDate.Year(), currDate.Month(), 1, 0, 0, 0, 0, currDate.Location())
+			} else if day <= 20 {
+				tmpDate = time.Date(currDate.Year(), currDate.Month(), 11, 0, 0, 0, 0, currDate.Location())
+			} else {
+				tmpDate = time.Date(currDate.Year(), currDate.Month(), 21, 0, 0, 0, 0, currDate.Location())
+			}
+		case "最后一天":
+			if day <= 10 {
+				tmpDate = time.Date(currDate.Year(), currDate.Month(), 10, 0, 0, 0, 0, currDate.Location())
+			} else if day <= 20 {
+				tmpDate = time.Date(currDate.Year(), currDate.Month(), 20, 0, 0, 0, 0, currDate.Location())
+			} else {
+				tmpDate = time.Date(currDate.Year(), currDate.Month()+1, 1, 0, 0, 0, 0, currDate.Location()).AddDate(0, 0, -1)
+			}
+		}
+		date = tmpDate.Format(utils.FormatDate)
+	case "本月":
+		var tmpDate time.Time
+		switch appointDay {
+		case "第一天":
+			tmpDate = time.Date(currDate.Year(), currDate.Month(), 1, 0, 0, 0, 0, currDate.Location())
+		case "最后一天":
+			tmpDate = time.Date(currDate.Year(), currDate.Month()+1, 1, 0, 0, 0, 0, currDate.Location()).AddDate(0, 0, -1)
+		}
+		date = tmpDate.Format(utils.FormatDate)
+	case "本季":
+		month := currDate.Month()
+		var tmpDate time.Time
+		switch appointDay {
+		case "第一天":
+			if month <= 3 {
+				tmpDate = time.Date(currDate.Year(), 1, 1, 0, 0, 0, 0, currDate.Location())
+			} else if month <= 6 {
+				tmpDate = time.Date(currDate.Year(), 4, 1, 0, 0, 0, 0, currDate.Location())
+			} else if month <= 9 {
+				tmpDate = time.Date(currDate.Year(), 7, 1, 0, 0, 0, 0, currDate.Location())
+			} else {
+				tmpDate = time.Date(currDate.Year(), 10, 1, 0, 0, 0, 0, currDate.Location())
+			}
+		case "最后一天":
+			if month <= 3 {
+				tmpDate = time.Date(currDate.Year(), 3, 31, 0, 0, 0, 0, currDate.Location())
+			} else if month <= 6 {
+				tmpDate = time.Date(currDate.Year(), 6, 30, 0, 0, 0, 0, currDate.Location())
+			} else if month <= 9 {
+				tmpDate = time.Date(currDate.Year(), 9, 30, 0, 0, 0, 0, currDate.Location())
+			} else {
+				tmpDate = time.Date(currDate.Year(), 12, 31, 0, 0, 0, 0, currDate.Location())
+			}
+		}
+		date = tmpDate.Format(utils.FormatDate)
+	case "本半年":
+		month := currDate.Month()
+		var tmpDate time.Time
+		switch appointDay {
+		case "第一天":
+			if month <= 6 {
+				tmpDate = time.Date(currDate.Year(), 1, 1, 0, 0, 0, 0, currDate.Location())
+			} else {
+				tmpDate = time.Date(currDate.Year(), 7, 1, 0, 0, 0, 0, currDate.Location())
+			}
+		case "最后一天":
+			if month <= 6 {
+				tmpDate = time.Date(currDate.Year(), 6, 30, 0, 0, 0, 0, currDate.Location())
+			} else {
+				tmpDate = time.Date(currDate.Year(), 12, 31, 0, 0, 0, 0, currDate.Location())
+			}
+		}
+		date = tmpDate.Format(utils.FormatDate)
+	case "本年":
+		var tmpDate time.Time
+		switch appointDay {
+		case "第一天":
+			tmpDate = time.Date(currDate.Year(), 1, 1, 0, 0, 0, 0, currDate.Location())
+		case "最后一天":
+			tmpDate = time.Date(currDate.Year(), 12, 31, 0, 0, 0, 0, currDate.Location())
+		}
+		date = tmpDate.Format(utils.FormatDate)
+	default:
+		errMsg = "错误的日期频度:" + frequency
+		err = errors.New(errMsg)
+		return
+	}
+
+	return
+}

+ 783 - 0
services/data/chart_info_excel_balance.go

@@ -0,0 +1,783 @@
+package data
+
+import (
+	"encoding/json"
+	"errors"
+	"eta/eta_mobile/models/data_manage"
+	excelModel "eta/eta_mobile/models/data_manage/excel"
+	"eta/eta_mobile/models/system"
+	"eta/eta_mobile/services/data/data_manage_permission"
+	"eta/eta_mobile/utils"
+	"fmt"
+	"math"
+	"sort"
+	"strings"
+	"time"
+)
+
+func GetBalanceExcelChartDetail(chartInfo *data_manage.ChartInfoView, mappingListTmp []*excelModel.ExcelChartEdb, sysUser *system.Admin, dataListMap map[int][]*data_manage.EdbDataList) (resp *data_manage.ChartInfoDetailResp, err error, errMsg string) {
+	// 图表数据权限
+	{
+		// 已授权分类id
+		permissionChartIdList, permissionClassifyIdList, e := data_manage_permission.GetUserChartAndClassifyPermissionList(sysUser.AdminId, chartInfo.ChartInfoId, chartInfo.ChartClassifyId)
+		if e != nil {
+			errMsg = "获取失败"
+			err = fmt.Errorf("获取已授权分类id数据失败,Err:" + err.Error())
+			return
+		}
+		chartInfo.HaveOperaAuth = data_manage_permission.CheckChartPermissionByPermissionIdList(chartInfo.IsJoinPermission, 0, chartInfo.ChartInfoId, chartInfo.ChartClassifyId, permissionChartIdList, permissionClassifyIdList)
+	}
+
+	chartInfoId := chartInfo.ChartInfoId
+	resp = new(data_manage.ChartInfoDetailResp)
+
+	// 获取主题样式
+	chartTheme, err := GetChartThemeConfig(chartInfo.ChartThemeId, 1, chartInfo.ChartType)
+	if err != nil {
+		errMsg = "获取失败"
+		err = fmt.Errorf(" 获取主题信息失败 Err:%s", err.Error())
+		return
+	}
+	chartInfo.ChartThemeStyle = chartTheme.Config
+	chartInfo.ChartThemeId = chartTheme.ChartThemeId
+
+	dateType := chartInfo.DateType
+	fmt.Println("dateType:", dateType)
+
+	chartType := chartInfo.ChartType
+	startDate := chartInfo.StartDate
+	endDate := chartInfo.EndDate
+	seasonStartDate := chartInfo.SeasonStartDate
+	seasonEndDate := chartInfo.SeasonEndDate
+	startYear := chartInfo.StartYear
+
+	calendar := chartInfo.Calendar
+
+	if calendar == "" {
+		calendar = "公历"
+	}
+
+	mappingList, err := TransferChartEdbToEdbMappingFormat(chartInfoId, chartType, mappingListTmp, dataListMap)
+	if err != nil {
+		return
+	}
+	if chartType == 2 {
+		startDate = seasonStartDate
+		endDate = seasonEndDate
+		if dateType <= 0 {
+			if startDate != "" {
+				dateType = 5
+			} else {
+				dateType = utils.DateTypeNYears
+			}
+		}
+	} else {
+		if dateType <= 0 {
+			dateType = 3
+		}
+	}
+	yearMax := 0
+	if dateType == utils.DateTypeNYears {
+		for _, v := range mappingList {
+			if v.LatestDate != "" {
+				lastDateT, tErr := time.Parse(utils.FormatDate, v.LatestDate)
+				if tErr != nil {
+					errMsg = "获取失败"
+					err = fmt.Errorf("获取图表日期信息失败,Err:" + tErr.Error())
+					return
+				}
+				if lastDateT.Year() > yearMax {
+					yearMax = lastDateT.Year()
+				}
+			}
+		}
+	}
+	startDate, endDate = utils.GetDateByDateTypeV2(dateType, startDate, endDate, startYear, yearMax)
+
+	if chartInfo.ChartType == 2 {
+		chartInfo.StartDate = startDate
+		chartInfo.EndDate = endDate
+	}
+	// 图表额外数据参数
+	extraConfigStr := chartInfo.ExtraConfig
+	// 柱方图的一些配置
+	var barConfig data_manage.BarChartInfoReq
+	if chartInfo != nil && chartInfo.ChartType == 7 {
+		if chartInfo.BarConfig == `` {
+			err = fmt.Errorf("柱方图未配置")
+			errMsg = "柱方图未配置"
+			return
+		}
+		err = json.Unmarshal([]byte(chartInfo.BarConfig), &barConfig)
+		if err != nil {
+			err = fmt.Errorf("柱方图配置异常 json.Unmarshal Err:%s", err.Error())
+			errMsg = "柱方图配置异常"
+			return
+		}
+		extraConfigStr = chartInfo.BarConfig
+	}
+	// 获取表格数据
+
+	excelChartInfoDataShow := new(ExcelChartInfoDataShow)
+	excelChartInfoDataShow.DataListMap = dataListMap
+
+	if chartInfo.HaveOperaAuth {
+		// 获取图表中的指标数据
+		edbList, xEdbIdValue, yDataList, dataResp, e, msg := GetChartEdbDataV2(chartInfoId, chartType, calendar, startDate, endDate, mappingList, extraConfigStr, chartInfo.SeasonExtraConfig, excelChartInfoDataShow)
+		if e != nil {
+			err = fmt.Errorf("获取图表,指标数据失败,Err:%s", e.Error())
+			errMsg = msg
+			return
+		}
+		// 单位
+		if chartType == utils.CHART_TYPE_BAR && len(yDataList) > 0 {
+			chartInfo.Unit = yDataList[0].Unit
+			chartInfo.UnitEn = yDataList[0].UnitEn
+		}
+		warnEdbList := make([]string, 0)
+		for _, v := range edbList {
+			if v.IsNullData {
+				warnEdbList = append(warnEdbList, v.EdbName+"("+v.EdbCode+")")
+			}
+		}
+		if len(warnEdbList) > 0 {
+			chartInfo.WarnMsg = `图表引用指标异常,异常指标:` + strings.Join(warnEdbList, ",")
+		}
+		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, e := data_manage.GetMyChartByCondition(myChartCondition, myChartPars)
+				if e != nil && e.Error() != utils.ErrNoRow() {
+					errMsg = "获取失败"
+					err = fmt.Errorf("获取我的图表信息失败,GetMyChartByCondition,Err:" + e.Error())
+					return
+				}
+				if myChartList != nil && len(myChartList) > 0 {
+					chartInfo.IsAdd = true
+					chartInfo.MyChartId = myChartList[0].MyChartId
+					chartInfo.MyChartClassifyId = myChartList[0].MyChartClassifyId
+				}
+			}
+		}
+		//判断是否需要展示英文标识
+		chartInfo.IsEnChart = CheckIsEnChart(chartInfo.ChartNameEn, edbList, chartInfo.Source, chartInfo.ChartType)
+
+		// 图表的指标来源
+		sourceNameList, sourceNameEnList := GetEdbSourceByEdbInfoIdList(edbList)
+
+		chartInfo.ChartSource = strings.Join(sourceNameList, ",")
+		chartInfo.ChartSourceEn = strings.Join(sourceNameEnList, ",")
+
+		// todo 指标权限
+		{
+			for _, item := range edbList {
+				// 数据权限
+				item.HaveOperaAuth = true
+			}
+		}
+
+		resp.EdbInfoList = edbList
+		resp.XEdbIdValue = xEdbIdValue
+		resp.YDataList = yDataList
+		resp.DataResp = dataResp
+	} else {
+		resp.EdbInfoList = mappingList
+	}
+
+	// todo 平衡表图表操作权限平衡表表格的操作权限保持一致,前端未用到该按钮权限,故不处理
+	chartInfo.IsEdit, _ = GetBalanceExcelInfoOpButtonByChartInfoId(sysUser.AdminId, chartInfo.ChartInfoId, chartInfo.HaveOperaAuth)
+	chartInfo.Button = data_manage.ChartViewButton{
+		IsEdit:    chartInfo.IsEdit,
+		IsEnChart: chartInfo.IsEnChart,
+		IsAdd:     chartInfo.IsAdd,
+		IsCopy:    true,
+		IsSetName: chartInfo.IsSetName,
+	}
+
+	resp.ChartInfo = chartInfo
+	resp.BarChartInfo = barConfig
+	return
+}
+
+// GetBalanceExcelEdbDataMapList 获取指标最后的基础数据
+func GetBalanceExcelEdbDataMapList(chartInfoId, chartType int, calendar, startDate, endDate string, mappingList []*data_manage.ChartEdbInfoMapping, seasonExtraConfig string, dataListMap map[int][]*data_manage.EdbDataList) (edbDataListMap map[int][]*data_manage.EdbDataList, edbList []*data_manage.ChartEdbInfoMapping, err error) {
+	// 指标对应的所有数据
+	edbDataListMap = make(map[int][]*data_manage.EdbDataList)
+
+	for _, v := range mappingList {
+		//fmt.Println("v:", v.EdbInfoId)
+		item := new(data_manage.ChartEdbInfoMapping)
+		item.EdbInfoId = v.EdbInfoId
+		item.SourceName = v.SourceName
+		item.Source = v.Source
+		item.EdbCode = v.EdbCode
+		item.EdbName = v.EdbName
+		item.EdbNameEn = v.EdbNameEn
+		item.Frequency = v.Frequency
+		item.EdbType = v.EdbType
+		item.FrequencyEn = GetFrequencyEn(v.Frequency)
+		if v.Unit != `无` {
+			item.Unit = v.Unit
+		}
+		item.UnitEn = v.UnitEn
+		item.StartDate = v.StartDate
+		item.EndDate = v.EndDate
+		item.ModifyTime = v.ModifyTime
+		item.EdbInfoCategoryType = v.EdbInfoCategoryType
+		item.PredictChartColor = v.PredictChartColor
+		item.ClassifyId = v.ClassifyId
+		if chartInfoId <= 0 {
+			item.IsAxis = 1
+			item.LeadValue = 0
+			item.LeadUnit = ""
+			item.ChartEdbMappingId = 0
+			item.ChartInfoId = 0
+			item.IsOrder = false
+			item.EdbInfoType = 1
+			item.ChartStyle = ""
+			item.ChartColor = ""
+			item.ChartWidth = 1
+			item.MaxData = v.MaxValue
+			item.MinData = v.MinValue
+		} else {
+			item.IsAxis = v.IsAxis
+			item.EdbInfoType = v.EdbInfoType
+			item.LeadValue = v.LeadValue
+			item.LeadUnit = v.LeadUnit
+			item.LeadUnitEn = GetLeadUnitEn(v.LeadUnit)
+			item.ChartEdbMappingId = v.ChartEdbMappingId
+			item.ChartInfoId = v.ChartInfoId
+			item.ChartStyle = v.ChartStyle
+			item.ChartColor = v.ChartColor
+			item.ChartWidth = v.ChartWidth
+			item.IsOrder = v.IsOrder
+			item.MaxData = v.MaxData
+			item.MinData = v.MinData
+		}
+		item.LatestValue = v.LatestValue
+		item.LatestDate = v.LatestDate
+		item.UniqueCode = v.UniqueCode
+		item.MoveLatestDate = v.LatestDate
+		item.EdbAliasName = v.EdbAliasName
+		item.IsConvert = v.IsConvert
+		item.ConvertType = v.ConvertType
+		item.ConvertValue = v.ConvertValue
+		item.ConvertUnit = v.ConvertUnit
+		item.ConvertEnUnit = v.ConvertEnUnit
+		item.IsJoinPermission = v.IsJoinPermission
+
+		var startDateReal string
+		var diffSeconds int64
+		if chartType == 2 { //季节性图
+			startDateReal = startDate
+			if len(mappingList) > 1 {
+				item.IsAxis = v.IsAxis
+			}
+		} else {
+			if v.EdbInfoType == 0 && v.LeadUnit != "" && v.LeadValue > 0 { //领先指标
+				var startTimeRealTemp time.Time
+				startDateParse, _ := time.Parse(utils.FormatDate, startDate)
+				switch v.LeadUnit {
+				case "天":
+					startTimeRealTemp = startDateParse.AddDate(0, 0, -v.LeadValue)
+				case "月":
+					startTimeRealTemp = startDateParse.AddDate(0, -v.LeadValue, 0)
+				case "季":
+					startTimeRealTemp = startDateParse.AddDate(0, -3*v.LeadValue, 0)
+				case "周":
+					startTimeRealTemp = startDateParse.AddDate(0, 0, -7*v.LeadValue)
+				case "年":
+					startTimeRealTemp = startDateParse.AddDate(-v.LeadValue, 0, 0)
+				}
+				if startTimeRealTemp.Before(startDateParse) {
+					startDateReal = startTimeRealTemp.Format(utils.FormatDate)
+					diffSeconds = (int64(startTimeRealTemp.UnixNano()) - int64(startDateParse.UnixNano())) / 1e6
+				} else {
+					startDateReal = startDate
+					diffSeconds = 0
+				}
+
+				// 预测指标的开始日期也要偏移
+				{
+					day, tmpErr := utils.GetDaysBetween2Date(utils.FormatDate, startDate, startDateReal)
+					if tmpErr != nil {
+						err = tmpErr
+						return
+					}
+					moveLatestDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, item.MoveLatestDate, time.Local)
+					if tmpErr != nil {
+						err = tmpErr
+						return
+					}
+					item.MoveLatestDate = moveLatestDateTime.AddDate(0, 0, day).Format(utils.FormatDate)
+				}
+			} else {
+				startDateReal = startDate
+			}
+		}
+		//fmt.Println("line 1011 chart:", v.Source, v.EdbInfoId, startDateReal, endDate)
+		calendarPreYear := 0
+		if calendar == "农历" {
+			newStartDateReal, e := time.Parse(utils.FormatDate, startDateReal)
+			if e != nil {
+				err = fmt.Errorf("时间解析 time.Parse(%s, %s) error: %v", utils.FormatDate, startDateReal, e)
+				return
+			}
+			calendarPreYear = newStartDateReal.Year() - 1
+			newStartDateReal = newStartDateReal.AddDate(-1, 0, 0)
+			startDateReal = newStartDateReal.Format(utils.FormatDate)
+		}
+		dataList := make([]*data_manage.EdbDataList, 0)
+		dataListTmp, ok := dataListMap[v.EdbInfoId]
+		if ok {
+			dataList = dataListTmp
+			// 对dataList 根据dataTimestamp 进行排序
+			sort.Slice(dataList, func(i, j int) bool {
+				return dataList[i].DataTimestamp < dataList[j].DataTimestamp
+			})
+		} else {
+			//err = errors.New(fmt.Sprint("获取失败,指标类型异常", v.EdbInfoId))
+			utils.FileLog.Info(fmt.Sprintf("获取失败,指标数据异常 %d", v.EdbInfoId))
+		}
+		if v.IsConvert == 1 {
+			switch v.ConvertType {
+			case 1:
+				for i, data := range dataList {
+					dataList[i].Value = data.Value * v.ConvertValue
+				}
+				//item.MaxData = item.MaxData * v.ConvertValue
+				//item.MinData = item.MinData * v.ConvertValue
+			case 2:
+				for i, data := range dataList {
+					dataList[i].Value = data.Value / v.ConvertValue
+				}
+				//item.MaxData = item.MaxData / v.ConvertValue
+				//item.MinData = item.MinData / v.ConvertValue
+			case 3:
+				for i, data := range dataList {
+					if data.Value <= 0 {
+						err = errors.New("数据中含有负数或0,无法对数运算")
+						return
+					}
+					dataList[i].Value = math.Log(data.Value) / math.Log(v.ConvertValue)
+				}
+				//item.MaxData = math.Log(item.MaxData) / math.Log(v.ConvertValue)
+				//item.MinData = math.Log(item.MinData) / math.Log(v.ConvertValue)
+			}
+		}
+
+		edbDataListMap[v.EdbInfoId] = dataList
+
+		if diffSeconds != 0 && v.EdbInfoType == 0 {
+			dataListLen := len(dataList)
+			for i := 0; i < dataListLen; i++ {
+				dataList[i].DataTimestamp = dataList[i].DataTimestamp - diffSeconds
+			}
+		}
+
+		if chartType == 2 && item.IsAxis == 1 {
+			latestDate, tmpErr := time.Parse(utils.FormatDate, v.LatestDate)
+			if tmpErr != nil {
+				//item.DataList = dataList
+				item.IsNullData = true
+				edbList = append(edbList, item)
+				continue
+			}
+
+			if calendar == "农历" {
+				if len(dataList) <= 0 {
+					result := new(data_manage.EdbDataResult)
+					item.DataList = result
+				} else {
+					result, tmpErr := data_manage.AddCalculateQuarterV6(dataList)
+					if tmpErr != nil {
+						err = errors.New("获取农历数据失败,Err:" + tmpErr.Error())
+						return
+					}
+					quarterDataList, tErr := GetSeasonEdbInfoDataListByXDateNong(result, latestDate, seasonExtraConfig, calendarPreYear)
+					if tErr != nil {
+						err = errors.New("获取季节性图表数据失败,Err:" + tErr.Error())
+						return
+					}
+					item.DataList = quarterDataList
+				}
+
+			} else {
+				quarterDataList, tErr := GetSeasonEdbInfoDataListByXDate(dataList, latestDate, seasonExtraConfig)
+				if tErr != nil {
+					err = errors.New("获取季节性图表数据失败,Err:" + tErr.Error())
+					return
+				}
+				item.DataList = quarterDataList
+			}
+		} else if chartType == 2 && item.IsAxis == 0 {
+			// 右轴数据处理
+			xStartDate := "01-01"
+
+			jumpYear := 0
+			var seasonExtra data_manage.SeasonExtraItem
+			if seasonExtraConfig != "" {
+				err = json.Unmarshal([]byte(seasonExtraConfig), &seasonExtra)
+				if err != nil {
+					return
+				}
+			}
+
+			if seasonExtra.XStartDate != "" {
+				xStartDate = seasonExtra.XStartDate
+				jumpYear = seasonExtra.JumpYear
+			}
+
+			length := len(dataList)
+			if length == 0 {
+				return
+			}
+			latestDate, tmpErr := time.Parse(utils.FormatDate, v.LatestDate)
+			if tmpErr != nil {
+				//item.DataList = dataList
+				item.IsNullData = true
+				edbList = append(edbList, item)
+				continue
+				err = errors.New(fmt.Sprint("获取最后实际数据的日期失败,Err:" + tmpErr.Error() + ";LatestDate:" + v.LatestDate))
+				return
+			}
+
+			var rightAxisDate time.Time
+			if jumpYear == 1 {
+				latestDate = latestDate.AddDate(-1, 0, 0)
+				latestDateStr := fmt.Sprintf("%d-%s", latestDate.Year(),xStartDate)
+				rightAxisDate, err = time.Parse(utils.FormatDate, latestDateStr)
+				if err != nil {
+					return
+				}
+			}
+
+			newDataList := make([]*data_manage.EdbDataList, 0)
+			for _, v := range dataList {
+				dataTime, e := time.Parse(utils.FormatDate, v.DataTime)
+				if e != nil {
+					err = errors.New("季节性图处理右轴指标数据转换日期失败,Err:" + e.Error())
+					return
+				}
+				if dataTime.Equal(rightAxisDate) || dataTime.After(rightAxisDate) {
+					newDataList = append(newDataList, v)
+				}
+			}
+			item.DataList = newDataList
+		} else if chartType == 7 || chartType == utils.CHART_TYPE_RADAR { //柱方图
+			//item.DataList = dataList
+		} else {
+			item.DataList = dataList
+		}
+		edbList = append(edbList, item)
+	}
+
+	return
+}
+
+func CheckBalanceChartCacheAndPermission(chartInfo *data_manage.ChartInfoView, isCache bool, sysUser *system.Admin) (resp *data_manage.ChartInfoDetailFromUniqueCodeResp, isOk bool, msg, errMsg string) {
+	//判断是否存在缓存,如果存在缓存,那么直接从缓存中获取
+	adminId := sysUser.AdminId
+	// todo 图表数据权限
+	// 已授权分类id
+	permissionChartIdList, permissionClassifyIdList, err := data_manage_permission.GetUserChartAndClassifyPermissionList(adminId, chartInfo.ChartInfoId, chartInfo.ChartClassifyId)
+	if err != nil {
+		errMsg = "获取已授权分类id数据失败,Err:" + err.Error()
+		return
+	}
+
+	defer func() {
+		if isOk {
+			// 图表权限校验
+			{
+				resp.ChartInfo.HaveOperaAuth = data_manage_permission.CheckChartPermissionByPermissionIdList(chartInfo.IsJoinPermission, 0, chartInfo.ChartInfoId, chartInfo.ChartClassifyId, permissionChartIdList, permissionClassifyIdList)
+
+				//图表操作权限
+				chartInfo.IsEdit = CheckOpChartPermission(sysUser, chartInfo.SysUserId, resp.ChartInfo.HaveOperaAuth)
+				chartInfo.Button = data_manage.ChartViewButton{
+					IsEdit:    chartInfo.IsEdit,
+					IsEnChart: chartInfo.IsEnChart,
+					IsAdd:     chartInfo.IsAdd,
+					IsCopy:    true,
+					IsSetName: chartInfo.IsSetName,
+				}
+
+				//if !resp.ChartInfo.HaveOperaAuth {
+				//	for _, v := range resp.EdbInfoList {
+				//		v.DataList = nil
+				//	}
+				//	resp.DataResp = nil
+				//	resp.XEdbIdValue = []int{}
+				//	resp.YDataList = []data_manage.YData{}
+				//}
+			}
+
+			// todo 是否需要返回平衡表指标权限即判断平衡表的表格数据权限
+			{
+				// 查询图表关联的表格ID
+				excelInfo, e := excelModel.GetExcelInfoByChartInfoId(chartInfo.ChartInfoId)
+				if e != nil {
+					errMsg = "获取图表关联的表格ID失败,Err:" + e.Error()
+					err = e
+					return
+				}
+				checkExcelInfo := excelInfo
+				if excelInfo.Source == utils.BALANCE_TABLE {
+					checkExcelInfoId := excelInfo.ExcelInfoId
+					if excelInfo.BalanceType == 1 {
+						checkExcelInfoId = excelInfo.RelExcelInfoId
+					} else {
+						if excelInfo.ParentId > 0 {
+							checkExcelInfoId = excelInfo.ParentId
+						}
+					}
+					if checkExcelInfoId != excelInfo.ExcelInfoId {
+						checkExcelInfo, err = excelModel.GetExcelInfoById(checkExcelInfoId)
+						if err != nil {
+							errMsg = "获取平衡表格信息失败"
+							err = errors.New("获取平衡表格信息失败,Err:" + err.Error())
+							return
+						}
+					}
+				}
+
+				haveOperaAuth, e := data_manage_permission.CheckExcelPermissionByExcelInfoId(checkExcelInfo.ExcelInfoId, checkExcelInfo.ExcelClassifyId, checkExcelInfo.IsJoinPermission, adminId)
+				if e != nil {
+					errMsg = "获取平衡表格数据权限失败"
+					err = errors.New("获取表格权限信息失败,Err" + e.Error())
+					return
+				}
+				// 数据权限
+				for _, v := range resp.EdbInfoList {
+					v.HaveOperaAuth = haveOperaAuth
+				}
+			}
+		}
+	}()
+	key := GetChartInfoDataKey(chartInfo.ChartInfoId)
+	if utils.Re == nil && isCache {
+		if utils.Re == nil && utils.Rc.IsExist(key) {
+			if redisData, err1 := utils.Rc.RedisBytes(key); err1 == nil {
+				err := json.Unmarshal(redisData, &resp)
+				if err != nil || resp == nil {
+					return
+				}
+				// 这里跟当前用户相关的信息重新查询写入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
+				}
+
+				//判断是否加入我的图库
+				{
+					var myChartCondition string
+					var myChartPars []interface{}
+					myChartCondition += ` AND a.admin_id=? `
+					myChartPars = append(myChartPars, 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
+					}
+				}
+
+				isOk = true
+				fmt.Println("source redis")
+				return
+			}
+		}
+	}
+	return
+}
+func getBalanceDataListStartDateAndValue(dataList []*data_manage.EdbDataList) (startDate, endDate string, startVal, endVal, maxVal, minVal float64) {
+	if len(dataList) == 0 {
+		return
+	}
+	startDate = dataList[0].DataTime
+	startVal = dataList[0].Value
+	maxVal = dataList[0].Value
+	minVal = dataList[0].Value
+	endDate = dataList[len(dataList)-1].DataTime
+	endVal = dataList[len(dataList)-1].Value
+	for _, v := range dataList {
+		if v.DataTime < startDate {
+			startDate = v.DataTime
+			startVal = v.Value
+		}
+		if v.DataTime > endDate {
+			endDate = v.DataTime
+			endVal = v.Value
+		}
+		if v.Value > maxVal {
+			maxVal = v.Value
+		}
+		if v.Value < minVal {
+			minVal = v.Value
+		}
+	}
+	return
+}
+
+func TransferChartEdbToEdbMappingFormat(chartInfoId, chartType int, mappingListTmp []*excelModel.ExcelChartEdb, dataListMap map[int][]*data_manage.EdbDataList) (mappingList []*data_manage.ChartEdbInfoMapping, err error) {
+	mappingList = make([]*data_manage.ChartEdbInfoMapping, 0)
+	//循环组装映射关系
+	for _, v := range mappingListTmp {
+		dataList := make([]*data_manage.EdbDataList, 0)
+		dataListTmp, ok := dataListMap[v.ExcelChartEdbId]
+		if ok {
+			dataList = dataListTmp
+		} else {
+			//err = errors.New(fmt.Sprint("获取失败,指标类型异常", v.ExcelChartEdbId))
+			utils.FileLog.Info(fmt.Sprintf("获取失败,指标数据异常 %d", v.ExcelChartEdbId))
+		}
+		startDateStr, endDateStr, _, endVal, maxValue, minValue := getBalanceDataListStartDateAndValue(dataList)
+		mapping := &data_manage.ChartEdbInfoMapping{
+			EdbInfoId:         v.ExcelChartEdbId,
+			SourceName:        "平衡表",
+			Source:            0,
+			SubSource:         0,
+			EdbCode:           v.EdbCode,
+			EdbName:           v.EdbName,
+			EdbAliasName:      v.EdbName,
+			EdbNameEn:         v.EdbNameEn,
+			EdbAliasNameEn:    "",
+			EdbType:           0,
+			Frequency:         "",
+			FrequencyEn:       "",
+			Unit:              v.Unit,
+			UnitEn:            v.UnitEn,
+			StartDate:         startDateStr,
+			EndDate:           endDateStr,
+			ModifyTime:        v.ModifyTime.Format(utils.FormatDateTime),
+			ChartEdbMappingId: v.ExcelChartEdbId,
+			ChartInfoId:       chartInfoId,
+			MaxData:           v.MaxData,
+			MinData:           v.MinData,
+			IsOrder:           v.IsOrder,
+			IsAxis:            v.IsAxis,
+			EdbInfoType:       v.EdbInfoType,
+			//EdbInfoCategoryType: 0,
+			LeadValue:         v.LeadValue,
+			LeadUnit:          v.LeadUnit,
+			LeadUnitEn:        "",
+			ChartStyle:        "",
+			ChartColor:        "",
+			PredictChartColor: "",
+			ChartWidth:        v.ChartWidth,
+			ChartType:         chartType,
+			LatestDate:        endDateStr,
+			LatestValue:       endVal,
+			MoveLatestDate:    "",
+			UniqueCode:        "",
+			MinValue:          minValue,
+			MaxValue:          maxValue,
+			DataList:          nil,
+			IsNullData:        false,
+			MappingSource:     0,
+			RegionType:        "",
+			ClassifyId:        0,
+			IsConvert:         0,
+			ConvertType:       0,
+			ConvertValue:      0,
+			ConvertUnit:       "",
+			ConvertEnUnit:     "",
+			IsJoinPermission:  0,
+			HaveOperaAuth:     true,
+		}
+		mappingList = append(mappingList, mapping)
+	}
+	return
+}
+
+// GetBalanceExcelInfoOpButtonByChartInfoId 获取图表权限
+func GetBalanceExcelInfoOpButtonByChartInfoId(sysUserId, chartInfoId int, chartHaveOperaAuth bool) (opButton bool, err error) {
+	// 如果没有数据权限,那么直接返回
+	if !chartHaveOperaAuth {
+		return
+	}
+	// 获取表格信息
+	excelInfo, e := excelModel.GetExcelInfoByChartInfoId(chartInfoId)
+	if e != nil {
+		err = fmt.Errorf("获取ETA表格失败 Err %s", e.Error())
+		return
+	}
+	checkExcelInfo := excelInfo
+	if excelInfo.Source == utils.BALANCE_TABLE {
+		checkExcelInfoId := excelInfo.ExcelInfoId
+		if excelInfo.BalanceType == 1 {
+			checkExcelInfoId = excelInfo.RelExcelInfoId
+		} else {
+			if excelInfo.ParentId > 0 {
+				checkExcelInfoId = excelInfo.ParentId
+			}
+		}
+		if checkExcelInfoId != excelInfo.ExcelInfoId {
+			checkExcelInfo, e = excelModel.GetExcelInfoById(checkExcelInfoId)
+			if e != nil {
+				err = fmt.Errorf("获取平衡表格信息失败,Err:" + e.Error())
+				return
+			}
+		}
+	} else {
+		return
+	}
+	// 数据权限
+	haveOperaAuth, e := data_manage_permission.CheckExcelPermissionByExcelInfoId(checkExcelInfo.ExcelInfoId, checkExcelInfo.ExcelClassifyId, checkExcelInfo.IsJoinPermission, sysUserId)
+	if e != nil {
+		err = fmt.Errorf("获取表格权限信息失败,Err" + e.Error())
+		return
+	}
+	// 如果没有数据权限,那么直接返回
+	if !haveOperaAuth {
+		return
+	}
+	//button := GetBalanceExcelInfoOpButton(sysUserId, checkExcelInfo.SysUserId, haveOperaAuth, checkExcelInfo.ExcelInfoId)
+
+	if sysUserId == checkExcelInfo.SysUserId {
+		opButton = true
+	} else {
+		obj := new(excelModel.ExcelWorker)
+		workerList, e := obj.GetByExcelInfoId(checkExcelInfo.ExcelInfoId)
+		if e == nil {
+			for _, v := range workerList {
+				if v.SysUserId == sysUserId {
+					opButton = true
+					break
+				}
+			}
+		}
+	}
+	return
+}

+ 46 - 0
services/data/chart_info_interface.go

@@ -0,0 +1,46 @@
+package data
+
+import (
+	"eta/eta_mobile/models/data_manage"
+	"eta/eta_mobile/models/data_manage/excel"
+)
+
+type ChartInfoDataShow interface {
+	GetEdbDataMapList(chartInfoId, chartType int, calendar, startDate, endDate string, mappingList []*data_manage.ChartEdbInfoMapping, seasonExtraConfig string) (edbDataListMap map[int][]*data_manage.EdbDataList, edbList []*data_manage.ChartEdbInfoMapping, err error)
+	GetChartEdbMappingListByEdbInfoIdList(edbIdList []int) (mappingList []*data_manage.ChartEdbInfoMapping, err error)
+}
+
+type BaseChartInfoDataShow struct {
+}
+
+// GetEdbDataMapList 获取指标最后的基础数据
+func (e *BaseChartInfoDataShow) GetEdbDataMapList(chartInfoId, chartType int, calendar, startDate, endDate string, mappingList []*data_manage.ChartEdbInfoMapping, seasonExtraConfig string) (edbDataListMap map[int][]*data_manage.EdbDataList, edbList []*data_manage.ChartEdbInfoMapping, err error) {
+	// 指标对应的所有数据
+	edbDataListMap, edbList, err = GetEdbDataMapList(chartInfoId, chartType, calendar, startDate, endDate, mappingList, seasonExtraConfig)
+	return
+}
+
+// GetChartEdbMappingListByEdbInfoIdList 获取指标最后的基础数据
+func (e *BaseChartInfoDataShow) GetChartEdbMappingListByEdbInfoIdList(edbIdList []int) (mappingList []*data_manage.ChartEdbInfoMapping, err error) {
+	mappingList, err = data_manage.GetChartEdbMappingListByEdbInfoIdList(edbIdList)
+	return
+}
+
+type ExcelChartInfoDataShow struct {
+	DataListMap    map[int][]*data_manage.EdbDataList
+	MappingListTmp []*excel.ExcelChartEdb
+}
+
+// GetEdbDataMapList 获取指标最后的基础数据
+func (e *ExcelChartInfoDataShow) GetEdbDataMapList(chartInfoId, chartType int, calendar, startDate, endDate string, mappingList []*data_manage.ChartEdbInfoMapping, seasonExtraConfig string) (edbDataListMap map[int][]*data_manage.EdbDataList, edbList []*data_manage.ChartEdbInfoMapping, err error) {
+	// 指标对应的所有数据
+	edbDataListMap, edbList, err = GetBalanceExcelEdbDataMapList(chartInfoId, chartType, calendar, startDate, endDate, mappingList, seasonExtraConfig, e.DataListMap)
+	return
+}
+
+// GetChartEdbMappingListByEdbInfoIdList 获取指标最后的基础数据
+func (e *ExcelChartInfoDataShow) GetChartEdbMappingListByEdbInfoIdList(edbIdList []int) (mappingList []*data_manage.ChartEdbInfoMapping, err error) {
+	// 指标对应的所有数据
+	mappingList, err = TransferChartEdbToEdbMappingFormat(0, 0, e.MappingListTmp, e.DataListMap)
+	return
+}

+ 57 - 0
services/data/chart_theme.go

@@ -5,6 +5,7 @@ import (
 	"errors"
 	"eta/eta_mobile/models/data_manage"
 	"eta/eta_mobile/models/data_manage/chart_theme"
+	"eta/eta_mobile/models/data_manage/chart_theme/request"
 	"eta/eta_mobile/utils"
 	"fmt"
 	"github.com/shopspring/decimal"
@@ -76,6 +77,10 @@ func GetThemePreviewChartEdbData(chartType int, calendar, startDate, endDate str
 
 	// 特殊图形数据处理
 	switch chartType {
+	case 2: // 季节性图
+		if seasonExtraConfig != "" {
+			dataResp, err = SeasonChartData(edbList, seasonExtraConfig)
+		}
 	case 7: // 柱形图
 		barChartConf := extraConfig.(data_manage.BarChartInfoReq)
 		xEdbIdValue, yDataList, err = BarChartData(mappingList, edbDataListMap, barChartConf.DateList, barChartConf.Sort)
@@ -172,6 +177,9 @@ func getThemePreviewEdbDataMapList(chartType int, calendar, startDate, endDate s
 		var diffSeconds int64
 		if chartType == 2 { //季节性图
 			startDateReal = startDate
+			if len(mappingList) > 1 {
+				item.IsAxis = v.IsAxis
+			}
 		} else {
 			if v.EdbInfoType == 0 && v.LeadUnit != "" && v.LeadValue > 0 { //领先指标
 				var startTimeRealTemp time.Time
@@ -580,6 +588,10 @@ func GetChartThemeConfig(chartThemeId, source, chartType int) (chartTheme *chart
 
 	// 如果找到了,那么就返回
 	if chartTheme != nil {
+		newConfig, e := ConvertOldChartOptions(chartTheme.Config)
+		if e == nil {
+			chartTheme.Config = newConfig
+		}
 		return
 	}
 
@@ -588,12 +600,20 @@ func GetChartThemeConfig(chartThemeId, source, chartType int) (chartTheme *chart
 	// 查找主题类型id
 	chartThemeType, err := chart_theme.GetChartThemeTypeByChartTypeAndSource(chartType, source)
 	if err != nil {
+		newConfig, e := ConvertOldChartOptions(chartTheme.Config)
+		if e == nil {
+			chartTheme.Config = newConfig
+		}
 		return
 	}
 
 	// 寻找默认的主题id
 	chartTheme, err = chart_theme.GetChartThemeId(chartThemeType.DefaultChartThemeId)
 	if err != nil && err.Error() != utils.ErrNoRow() {
+		newConfig, e := ConvertOldChartOptions(chartTheme.Config)
+		if e == nil {
+			chartTheme.Config = newConfig
+		}
 		return
 	}
 
@@ -607,5 +627,42 @@ func GetChartThemeConfig(chartThemeId, source, chartType int) (chartTheme *chart
 	// 如果还是没找到,那就系统的主题id
 	chartTheme, err = chart_theme.GetSystemChartTheme(chartThemeType.ChartThemeTypeId)
 
+	// 兼容历史数据,加入新字段LineOptionList
+	newConfig, e := ConvertOldChartOptions(chartTheme.Config)
+	if e == nil {
+		chartTheme.Config = newConfig
+	}
+
 	return
 }
+
+
+// 兼容历史数据,加入新字段LineOptionList
+func ConvertOldChartOptions(config string) (newConfig string, err error) {
+	var oldTheme request.OldChartOptions
+
+	var newTheme request.NewChartOptions
+	err = json.Unmarshal([]byte(config), &oldTheme)
+	if err != nil {
+		return
+	}
+	if oldTheme.LineOptionList != nil && len(oldTheme.LineOptionList) > 0 {
+		newConfig = config
+		return
+	}
+	newTheme.OldChartOptions = oldTheme
+	for i := 0; i < 10; i++ {
+		newLineOption := request.NewLineOptions{
+			LineOptions: oldTheme.LineOptions,
+			Color:       oldTheme.ColorsOptions[i],
+			DataMark:    "none",
+			MarkType:    "square",
+			MarkSize:    5,
+			MarkColor:   oldTheme.ColorsOptions[i],
+		}
+		newTheme.LineOptionList = append(newTheme.LineOptionList, newLineOption)
+	}
+	newThemeStr, _ := json.Marshal(newTheme)
+	newConfig = string(newThemeStr)
+	return
+}

+ 120 - 2
services/data/correlation/chart_info.go

@@ -564,11 +564,13 @@ func GetRollingCorrelationChartDataByEdbInfo(edbInfoMappingA, edbInfoMappingB *d
 }
 
 // ChartInfoRefresh 图表刷新
-func ChartInfoRefresh(chartInfoId int) (err error) {
+func ChartInfoRefresh(chartInfoId int, uniqueCode string) (isAsync bool, err error) {
 	var errMsg string
 	defer func() {
 		if err != nil {
-			go alarm_msg.SendAlarmMsg("CorrelationChartInfoRefresh: "+errMsg, 3)
+			tips := fmt.Sprintf("CorrelationChartInfoRefresh: %s", errMsg)
+			utils.FileLog.Info(tips)
+			go alarm_msg.SendAlarmMsg(tips, 3)
 		}
 	}()
 	correlationChart := new(data_manage.ChartInfoCorrelation)
@@ -577,6 +579,53 @@ func ChartInfoRefresh(chartInfoId int) (err error) {
 		return
 	}
 
+	// 多因子刷新-异步
+	if correlationChart.AnalysisMode == 1 {
+		isAsync = true
+
+		go func() {
+			// 1.刷新图表关联的指标
+			mappings, e := data_manage.GetChartEdbMappingList(chartInfoId)
+			if e != nil {
+				utils.FileLog.Info(fmt.Sprintf("获取图表关联指标失败, err: %v", e))
+				return
+			}
+			if len(mappings) == 0 {
+				utils.FileLog.Info("图表无关联指标")
+				return
+			}
+			var edbIds []int
+			for _, v := range mappings {
+				edbIds = append(edbIds, v.EdbInfoId)
+			}
+			if e, _ = data.EdbInfoRefreshAllFromBaseV3(edbIds, false, true, false); e != nil {
+				utils.FileLog.Info(fmt.Sprintf("批量刷新指标失败, err: %v", e))
+				return
+			}
+
+			// 2.刷新指标系列计算数据
+			for _, v := range mappings {
+				_, e = data.PostRefreshFactorEdbRecalculate(v.EdbInfoId, v.EdbCode)
+				if e != nil {
+					utils.FileLog.Info(fmt.Sprintf("PostRefreshFactorEdbRecalculate err: %v", e))
+					continue
+				}
+			}
+
+			// 3.刷新图表矩阵
+			_, e = data.PostRefreshFactorEdbChartRecalculate(chartInfoId)
+			if e != nil {
+				utils.FileLog.Info(fmt.Sprintf("PostRefreshFactorEdbRecalculate err: %v", e))
+				return
+			}
+
+			// 4.清除图表缓存
+			key := utils.HZ_CHART_LIB_DETAIL + uniqueCode
+			_ = utils.Rc.Delete(key)
+		}()
+		return
+	}
+
 	// 批量刷新ETA指标
 	err, _ = data.EdbInfoRefreshAllFromBaseV3([]int{correlationChart.EdbInfoIdFirst, correlationChart.EdbInfoIdSecond}, false, true, false)
 	if err != nil {
@@ -1218,3 +1267,72 @@ func CopyChartInfo(configId, classifyId int, chartName string, correlationChartI
 
 	return
 }
+
+// GetFactorChartDataByChartId 获取多因子相关性图表数据
+func GetFactorChartDataByChartId(chartInfoId int, extraConfig string) (xEdbIdValue []int, yDataList []data_manage.YData, err error) {
+	if chartInfoId <= 0 {
+		return
+	}
+	// 指标对应的图例
+	extra := new(data_manage.CorrelationChartInfoExtraConfig)
+	if extraConfig != "" {
+		if e := json.Unmarshal([]byte(extraConfig), extra); e != nil {
+			err = fmt.Errorf("解析图表额外配置失败, err: %v", e)
+			return
+		}
+	}
+	legends := make(map[string]*data_manage.CorrelationChartLegend)
+	if extra != nil {
+		for _, v := range extra.LegendConfig {
+			s := fmt.Sprintf("%d-%d", v.SeriesId, v.EdbInfoId)
+			legends[s] = v
+		}
+	}
+
+	// 获取图表引用到的系列指标
+	chartMappingOb := new(data_manage.FactorEdbSeriesChartMapping)
+	cond := fmt.Sprintf(" AND %s = ? AND %s = 1", chartMappingOb.Cols().ChartInfoId, chartMappingOb.Cols().EdbUsed)
+	pars := make([]interface{}, 0)
+	pars = append(pars, chartInfoId)
+	chartMappings, e := chartMappingOb.GetItemsByCondition(cond, pars, []string{}, "")
+	if e != nil {
+		err = fmt.Errorf("获取图表引用系列指标失败")
+		return
+	}
+
+	// 取出计算结果
+	yDataList = make([]data_manage.YData, 0)
+	yDate := "0000-00-00"
+	for k, m := range chartMappings {
+		var values []data_manage.FactorEdbSeriesCorrelationMatrixValues
+		if m.CalculateData != "" {
+			e = json.Unmarshal([]byte(m.CalculateData), &values)
+			if e != nil {
+				err = fmt.Errorf("系列指标计算数据有误, err: %v", e)
+				return
+			}
+		}
+		var y []float64
+		for _, v := range values {
+			if k == 0 {
+				xEdbIdValue = append(xEdbIdValue, v.XData)
+			}
+			y = append(y, v.YData)
+		}
+		var yData data_manage.YData
+		yData.Date = yDate
+		yData.Value = y
+		yData.SeriesEdb.SeriesId = m.FactorEdbSeriesId
+		yData.SeriesEdb.EdbInfoId = m.EdbInfoId
+
+		// 图例
+		s := fmt.Sprintf("%d-%d", m.FactorEdbSeriesId, m.EdbInfoId)
+		legend := legends[s]
+		if legend != nil {
+			yData.Name = legend.LegendName
+			yData.Color = legend.Color
+		}
+		yDataList = append(yDataList, yData)
+	}
+	return
+}

+ 230 - 0
services/data/edb_data.go

@@ -4,9 +4,11 @@ import (
 	"errors"
 	"eta/eta_mobile/models"
 	"eta/eta_mobile/models/data_manage"
+	"eta/eta_mobile/models/mgo"
 	"eta/eta_mobile/utils"
 	"fmt"
 	"github.com/shopspring/decimal"
+	"go.mongodb.org/mongo-driver/bson"
 	"time"
 )
 
@@ -390,3 +392,231 @@ func GetEdbBeforeAndAfterDateData(targetDate string, dataList []*data_manage.Edb
 	}
 	return
 }
+
+// GetPageData
+// @Description: 获取指标的分页数据
+// @author: Roc
+// @datetime 2024-05-07 10:33:02
+// @param edbInfoId int
+// @param source int
+// @param subSource int
+// @param startSize int
+// @param pageSize int
+// @return dataCount int
+// @return dataList []*data_manage.EdbData
+// @return err error
+func GetPageData(edbInfoId, source, subSource int, endDataTime string, startSize, pageSize int) (dataCount int, dataList []*data_manage.EdbData, err error) {
+	dataList = make([]*data_manage.EdbData, 0)
+
+	// 自有数据需要额外处理(从mongo获取)
+	if source == utils.DATA_SOURCE_BUSINESS && utils.UseMongo {
+		return getPageDataByMongo(edbInfoId, source, subSource, endDataTime, startSize, pageSize)
+	}
+
+	// 默认走mysql
+	return getPageDataByMysql(edbInfoId, source, subSource, endDataTime, startSize, pageSize)
+}
+
+// getPageDataByMysql
+// @Description: 从Mysql获取数据
+// @author: Roc
+// @datetime 2024-05-07 15:08:41
+// @param edbInfoId int
+// @param source int
+// @param subSource int
+// @param endDataTime string
+// @param startSize int
+// @param pageSize int
+// @return dataCount int
+// @return dataList []*data_manage.EdbData
+// @return err error
+func getPageDataByMysql(edbInfoId, source, subSource int, endDataTime string, startSize, pageSize int) (dataCount int, dataList []*data_manage.EdbData, err error) {
+	dataList = make([]*data_manage.EdbData, 0)
+	var dataCondition string
+	var dataPars []interface{}
+
+	dataCondition += ` AND edb_info_id=? `
+	dataPars = append(dataPars, edbInfoId)
+
+	// 结束日期
+	if endDataTime != "" {
+		dataCondition += ` AND data_time <= ? `
+		dataPars = append(dataPars, endDataTime)
+	}
+
+	// 获取数据总量
+	dataCount, err = data_manage.GetEdbDataCountByCondition(dataCondition, dataPars, source, subSource)
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		return
+	}
+
+	// 获取列表数据
+	dataList, err = data_manage.GetEdbDataListByCondition(dataCondition, dataPars, source, subSource, pageSize, startSize)
+	if err != nil {
+		return
+	}
+
+	return
+}
+
+// getPageDataByMongo
+// @Description: 从MongoDB获取数据
+// @author: Roc
+// @datetime 2024-05-07 15:06:42
+// @param edbInfoId int
+// @param source int
+// @param subSource int
+// @param endDataTime string
+// @param startSize int
+// @param pageSize int
+// @return dataCount int
+// @return dataList []*data_manage.EdbData
+// @return err error
+func getPageDataByMongo(edbInfoId, source, subSource int, endDataTime string, startSize, pageSize int) (dataCount int, dataList []*data_manage.EdbData, err error) {
+	dataList = make([]*data_manage.EdbData, 0)
+
+	mogDataObj := mgo.EdbDataBusiness{}
+	// 构建查询条件
+	queryConditions := bson.M{
+		"edb_info_id": edbInfoId,
+	}
+	// 结束日期
+	dateCondition, err := mgo.BuildDateCondition("", endDataTime)
+	if err != nil {
+		return
+	}
+	if len(dateCondition) > 0 {
+		queryConditions["data_time"] = dateCondition
+	}
+
+	// 获取数据总量
+	tmpCount, tmpErr := mogDataObj.GetCountDataList(queryConditions)
+	if tmpErr != nil && tmpErr.Error() != utils.ErrNoRow() {
+		err = tmpErr
+		return
+	}
+	dataCount = int(tmpCount)
+
+	// 获取列表数据
+	tmpDataList, tmpErr := mogDataObj.GetPageDataList(queryConditions, int64(startSize), int64(pageSize), []string{"-data_time"})
+	if tmpErr != nil {
+		err = tmpErr
+		return
+	}
+	for k, v := range tmpDataList {
+		dataList = append(dataList, &data_manage.EdbData{
+			EdbDataId: k + 1,
+			EdbInfoId: v.EdbInfoId,
+			DataTime:  v.DataTime.Format(utils.FormatDate),
+			Value:     v.Value,
+		})
+	}
+
+	return
+}
+
+// GetEdbDataTbzForSeason 获取指标的同比值数据
+func GetEdbDataTbzForSeason(frequency string, tmpDataList []*data_manage.EdbDataList, startDateTime time.Time) (dataList []*data_manage.EdbDataList, minValue, maxValue float64, err error) {
+	dataList = make([]*data_manage.EdbDataList, 0)
+
+	// 数据处理
+	var dateArr []string
+	dataMap := make(map[string]*data_manage.EdbDataList)
+	for _, v := range tmpDataList {
+		dateArr = append(dateArr, v.DataTime)
+		dataMap[v.DataTime] = v
+	}
+	for _, av := range dateArr {
+		currentItem, ok := dataMap[av]
+		// 如果找不到当前日期的数据,那么终止当前循环,进入下一循环
+		if !ok {
+			continue
+		}
+		tmpItem := *currentItem
+		var isOk bool //是否计算出来结果
+
+		//当前日期
+		currentDate, tmpErr := time.ParseInLocation(utils.FormatDate, av, time.Local)
+		if tmpErr != nil {
+			err = tmpErr
+			return
+		}
+		// 如果存在开始日期,同时,当前日期早于开始日期,那么终止当前循环,进入下一循环
+		if !startDateTime.IsZero() && currentDate.Before(startDateTime) {
+			continue
+		}
+		//上一年的日期
+		preDate := currentDate.AddDate(-1, 0, 0)
+		preDateStr := preDate.Format(utils.FormatDate)
+		if findItem, ok := dataMap[preDateStr]; ok { //上一年同期找到
+			tmpItem.Value = TbzDiv(currentItem.Value, findItem.Value)
+			isOk = true
+		} else {
+			if frequency == "月度" { //向上和向下,各找一个月
+				for i := 0; i <= 35; i++ {
+					nextDateDay := preDate.AddDate(0, 0, i)
+					nextDateDayStr := nextDateDay.Format(utils.FormatDate)
+					if findItem, ok := dataMap[nextDateDayStr]; ok { //上一年同期->下一个月找到
+						tmpItem.Value = TbzDiv(currentItem.Value, findItem.Value)
+						isOk = true
+						break
+					} else {
+						preDateDay := preDate.AddDate(0, 0, -i)
+						preDateDayStr := preDateDay.Format(utils.FormatDate)
+						if findItem, ok := dataMap[preDateDayStr]; ok { //上一年同期->上一个月找到
+							tmpItem.Value = TbzDiv(currentItem.Value, findItem.Value)
+							isOk = true
+							break
+						}
+					}
+				}
+			} else if frequency == "季度" || frequency == "年度" {
+				if findItem, ok := dataMap[preDateStr]; ok { //上一年同期->下一个月找到
+					tmpItem.Value = TbzDiv(currentItem.Value, findItem.Value)
+					isOk = true
+					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 { //上一年同期->下一个月找到
+						tmpItem.Value = TbzDiv(currentItem.Value, findItem.Value)
+						isOk = true
+						break
+					} else {
+						if i >= 1 {
+							preDateDay = preDate.AddDate(0, 0, -i)
+							preDateDayStr = nextDateDay.Format(utils.FormatDate)
+						}
+						if findItem, ok := dataMap[preDateDayStr]; ok { //上一年同期->上一个月找到
+							tmpItem.Value = TbzDiv(currentItem.Value, findItem.Value)
+							isOk = true
+							break
+						}
+					}
+				}
+			}
+		}
+
+		if isOk {
+			if tmpItem.Value > maxValue {
+				maxValue = tmpItem.Value
+			}
+			if tmpItem.Value < minValue {
+				minValue = tmpItem.Value
+			}
+			dataList = append(dataList, &tmpItem)
+		}
+	}
+
+	return
+}

+ 50 - 3
services/data/edb_info.go

@@ -103,8 +103,11 @@ func EdbInfoRefreshAllFromBaseV3(edbInfoIdList []int, refreshAll, isSync, isRefr
 	}
 
 	// 需要刷新的指标数量
-	totalEdbInfo := len(newBaseEdbInfoArr) + len(calculateArr) + len(predictCalculateArr)
-
+	// totalEdbInfo := len(newBaseEdbInfoArr) + len(calculateArr) + len(predictCalculateArr)
+	totalEdbInfo := len(newBaseEdbInfoArr) + len(calculateArr) + len(predictCalculateArr) + len(newBasePredictEdbInfoArr)
+	if totalEdbInfo == 0 {
+		return
+	}
 	if totalEdbInfo <= 20 || isSync {
 		err = edbInfoRefreshAll(refreshAll, newBaseEdbInfoArr, newBasePredictEdbInfoArr, newCalculateMap, newPredictCalculateMap, calculateArr, predictCalculateArr)
 	} else {
@@ -173,6 +176,9 @@ func getEdbInfoIdList(edbInfoIdList []int) (newBaseEdbInfoArr, newBasePredictEdb
 		// 普通计算指标
 		for _, edbInfo := range tmpCalculateMap {
 			if _, ok := newCalculateMap[edbInfo.EdbInfoId]; !ok {
+				if edbInfo.NoUpdate == 1 {
+					continue
+				}
 				newCalculateMap[edbInfo.EdbInfoId] = edbInfo
 				calculateArr = append(calculateArr, edbInfo.EdbInfoId)
 			}
@@ -1718,8 +1724,48 @@ func getRefreshEdbInfoListByIds(edbInfoIdList []int) (newBaseEdbInfoArr, newBase
 	return
 }
 
+type AddEdbBaseInfoReq struct {
+	EdbCode         string `description:"指标编码"`
+	EdbName         string `description:"指标名称"`
+	Unit            string `description:"单位"`
+	ClassifyId      int    `description:"所属分类"`
+	SysUserId       int    `description:"用户id"`
+	SysUserRealName string `description:"用户真实名称"`
+}
+
 // EdbInfoAdd 添加指标到指标库
 func EdbInfoAdd(source, subSource, classifyId int, edbCode, edbName, frequency, unit, startDate, endDate string, sysUserId int, sysUserRealName, lang string) (edbInfo *data_manage.EdbInfo, err error, errMsg string, isSendEmail bool) {
+	// 有些指标的添加是走的指标公共服务
+	if source == utils.DATA_SOURCE_BUSINESS {
+		req2 := AddEdbBaseInfoReq{
+			EdbCode:         edbCode,
+			EdbName:         edbName,
+			Unit:            unit,
+			ClassifyId:      classifyId,
+			SysUserId:       sysUserId,
+			SysUserRealName: sysUserRealName,
+		}
+		reqJson, tmpErr := json.Marshal(req2)
+		if tmpErr != nil {
+			err = tmpErr
+			return
+		}
+		respItem, tmpErr := AddBaseEdbInfo(string(reqJson), source, subSource, lang)
+		if tmpErr != nil {
+			errMsg = "添加失败"
+			err = tmpErr
+			return
+		}
+		isSendEmail = respItem.IsSendEmail
+		if respItem.Ret != 200 {
+			errMsg = respItem.Msg
+			err = errors.New(respItem.ErrMsg)
+		} else {
+			edbInfo, err = data_manage.GetEdbInfoById(respItem.Data.EdbInfoId)
+		}
+		return
+	}
+
 	isSendEmail = true
 
 	//判断指标名称是否存在
@@ -2111,7 +2157,7 @@ func getEdbRuleTitle(edbInfo, parentEdbInfo *data_manage.EdbInfo, childList []da
 			for _, v := range edbMappingList {
 				if v.FromEdbInfoId == edbInfo.EdbInfoId {
 					edbName = fmt.Sprintf("%s(%s)", edbInfo.EdbName, v.FromTag)
-					edbName = fmt.Sprintf("%s(%s)", edbInfo.EdbNameEn, v.FromTag)
+					edbNameEn = fmt.Sprintf("%s(%s)", edbInfo.EdbNameEn, v.FromTag)
 				}
 			}
 
@@ -2152,6 +2198,7 @@ func getEdbRuleTitle(edbInfo, parentEdbInfo *data_manage.EdbInfo, childList []da
 			for _, v := range edbMappingList {
 				if v.FromEdbInfoId == edbInfo.EdbInfoId {
 					edbName = fmt.Sprintf("%s(%s)", edbInfo.EdbName, v.FromTag)
+					edbNameEn = fmt.Sprintf("%s(%s)", edbInfo.EdbNameEn, v.FromTag)
 				}
 			}
 

+ 141 - 103
services/data/edb_info_calculate.go

@@ -7,10 +7,9 @@ import (
 	"eta/eta_mobile/utils"
 	"fmt"
 	"github.com/shopspring/decimal"
-	"github.com/yidane/formula"
 	"math"
 	"regexp"
-	"strconv"
+	"sort"
 	"strings"
 	"time"
 )
@@ -365,107 +364,6 @@ func GetFormulaMap() map[string]string {
 	return funMap
 }
 
-// 刷新数据
-func RefreshCalculate(edbInfoIdArr []*data_manage.EdbInfo, edbInfoId int, edbCode, formulaStr, startDate, endDate string, edbInfoIdBytes []string) (err error) {
-	defer func() {
-		if err != nil {
-			fmt.Println("RefreshCalculate:Err " + err.Error())
-			utils.FileLog.Info("Calculate Err:%s" + err.Error())
-		}
-	}()
-	saveDataMap := make(map[string]map[int]float64)
-	for _, v := range edbInfoIdArr {
-		var condition string
-		var pars []interface{}
-		condition += " AND edb_info_id=? "
-		pars = append(pars, v.EdbInfoId)
-		if startDate != "" {
-			condition += " AND data_time>=? "
-			pars = append(pars, startDate)
-		}
-		if endDate != "" {
-			condition += " AND data_time<=? "
-			pars = append(pars, endDate)
-		}
-		dataList, err := data_manage.GetEdbDataListAll(condition, pars, v.Source, v.SubSource, 1)
-		if err != nil {
-			return 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
-			}
-
-			count, err := data_manage.GetEdbDataCalculateByCodeAndDate(edbCode, sk)
-			if err != nil && err.Error() != utils.ErrNoRow() {
-				return err
-			}
-			if count <= 0 { //需要存入的数据
-				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
-			} else {
-				calVal = utils.FixFloat(calVal, 4)
-				err = data_manage.ModifyEdbDataCalculate(int64(edbInfoId), sk, calVal)
-				if err != nil {
-					return err
-				}
-			}
-		}
-	}
-	if isAdd {
-		addSql = strings.TrimRight(addSql, ",")
-		data_manage.AddEdbDataCalculateBySql(addSql)
-		if err != nil {
-			fmt.Println("AddEdbDataCalculate Err:" + err.Error())
-			return err
-		}
-	}
-	return
-}
-
 // 处理整个数据
 func handleDateSaveDataMap(dateList []string, realSaveDataMap, saveDataMap map[string]map[int]float64, edbInfoIdArr []*data_manage.EdbInfo, emptyType int) {
 	var startDate, endDate string
@@ -762,3 +660,143 @@ func GetMaxMinEdbInfo(formula string) string {
 	formula = strings.ReplaceAll(formula, "min", "MIN")
 	return formula
 }
+
+
+// HandleDataByLinearRegressionToList 插值法补充数据(线性方程式)
+func HandleDataByLinearRegressionToList (edbInfoDataList []*data_manage.EdbDataList, handleDataMap map[string]float64) (dataTimeList []string,valueList []float64, err error) {
+	if len(edbInfoDataList) < 2 {
+		return
+	}
+
+	var startEdbInfoData *data_manage.EdbDataList
+	for _, v := range edbInfoDataList {
+		handleDataMap[v.DataTime] = v.Value
+		dataTimeList = append(dataTimeList, v.DataTime)
+		// 第一个数据就给过滤了,给后面的试用
+		if startEdbInfoData == nil {
+			startEdbInfoData = v
+			//startEdbInfoData.DataTime = startEdbInfoData.DataTime[:5]+ "01-01"
+			continue
+		}
+
+		// 获取两条数据之间相差的天数
+		startDataTime, _ := time.ParseInLocation(utils.FormatDate, startEdbInfoData.DataTime, time.Local)
+		currDataTime, _ := time.ParseInLocation(utils.FormatDate, v.DataTime, time.Local)
+		betweenHour := int(currDataTime.Sub(startDataTime).Hours())
+		betweenDay := betweenHour / 24
+
+		// 如果相差一天,那么过滤
+		if betweenDay <= 1 {
+			startEdbInfoData = v
+			continue
+		}
+
+		// 生成线性方程式
+		var a, b float64
+		{
+			coordinateData := make([]utils.Coordinate, 0)
+			tmpCoordinate1 := utils.Coordinate{
+				X: 1,
+				Y: startEdbInfoData.Value,
+			}
+			coordinateData = append(coordinateData, tmpCoordinate1)
+			tmpCoordinate2 := utils.Coordinate{
+				X: float64(betweenDay) + 1,
+				Y: v.Value,
+			}
+			coordinateData = append(coordinateData, tmpCoordinate2)
+
+			a, b = utils.GetLinearResult(coordinateData)
+			if math.IsNaN(a) || math.IsNaN(b) {
+				err = errors.New("线性方程公式生成失败")
+				return
+			}
+		}
+
+		// 生成对应的值
+		{
+			for i := 1; i < betweenDay; i++ {
+				tmpDataTime := startDataTime.AddDate(0, 0, i)
+				aDecimal := decimal.NewFromFloat(a)
+				xDecimal := decimal.NewFromInt(int64(i) + 1)
+				bDecimal := decimal.NewFromFloat(b)
+
+				val, _ := aDecimal.Mul(xDecimal).Add(bDecimal).Round(4).Float64()
+				handleDataMap[tmpDataTime.Format(utils.FormatDate)] = val
+				dataTimeList = append(dataTimeList, tmpDataTime.Format(utils.FormatDate))
+				valueList = append(valueList, val)
+			}
+		}
+
+		startEdbInfoData = v
+	}
+
+	return
+}
+
+// HandleDataByLinearRegressionToList 保证生成365个数据点的线性插值法
+func HandleDataByLinearRegressionToListV2(edbInfoDataList []*data_manage.EdbDataList, handleDataMap map[string]float64) (dataTimeList []string, valueList []float64, err error) {
+	if len(edbInfoDataList) < 2 {
+		return
+	}
+
+	// 确保至少有两天数据来生成线性方程
+	if len(edbInfoDataList) < 2 {
+		err = errors.New("至少需要两天的数据来执行线性插值")
+		return
+	}
+
+	// 对数据按日期排序,确保顺序正确
+	sort.Slice(edbInfoDataList, func(i, j int) bool {
+		t1, _ := time.ParseInLocation(utils.FormatDate, edbInfoDataList[i].DataTime, time.Local)
+		t2, _ := time.ParseInLocation(utils.FormatDate, edbInfoDataList[j].DataTime, time.Local)
+		return t1.Before(t2)
+	})
+
+	startEdbInfoData := edbInfoDataList[0]
+	endEdbInfoData := edbInfoDataList[len(edbInfoDataList)-1]
+
+	// 计算起始和结束日期间实际的天数
+	startDate, _ := time.ParseInLocation(utils.FormatDate, startEdbInfoData.DataTime, time.Local)
+	endDate, _ := time.ParseInLocation(utils.FormatDate, endEdbInfoData.DataTime, time.Local)
+	actualDays := endDate.Sub(startDate).Hours() / 24
+
+	// 生成365个数据点,首先处理已有数据
+	for _, v := range edbInfoDataList {
+		handleDataMap[v.DataTime] = v.Value
+		dataTimeList = append(dataTimeList, v.DataTime)
+		valueList = append(valueList, v.Value)
+	}
+
+	// 如果已有数据跨越天数不足365天,则对缺失的日期进行线性插值
+	if actualDays < 365 {
+		// 使用已有数据点生成线性方程(这里简化处理,实际可能需更细致处理边界情况)
+		var a, b float64
+		coordinateData := []utils.Coordinate{
+			{X: 1, Y: startEdbInfoData.Value},
+			{X: float64(len(edbInfoDataList)), Y: endEdbInfoData.Value},
+		}
+		a, b = utils.GetLinearResult(coordinateData)
+		if math.IsNaN(a) || math.IsNaN(b) {
+			err = errors.New("线性方程公式生成失败")
+			return
+		}
+
+		// 对剩余日期进行插值
+		for i := 1; i < 365; i++ {
+			day := startDate.AddDate(0, 0, i)
+			if _, exists := handleDataMap[day.Format(utils.FormatDate)]; !exists {
+				aDecimal := decimal.NewFromFloat(a)
+				xDecimal := decimal.NewFromInt(int64(i) + 1)
+				bDecimal := decimal.NewFromFloat(b)
+
+				val, _ := aDecimal.Mul(xDecimal).Add(bDecimal).Round(4).Float64()
+				handleDataMap[day.Format(utils.FormatDate)] = val
+				dataTimeList = append(dataTimeList, day.Format(utils.FormatDate))
+				valueList = append(valueList, val)
+			}
+		}
+	}
+
+	return
+}

+ 408 - 0
services/data/excel/balance_table.go

@@ -0,0 +1,408 @@
+package excel
+
+import (
+	"encoding/json"
+	"errors"
+	"eta/eta_mobile/models/data_manage"
+	excelModel "eta/eta_mobile/models/data_manage/excel"
+	"eta/eta_mobile/models/data_manage/excel/request"
+	"eta/eta_mobile/utils"
+	"fmt"
+	"github.com/xuri/excelize/v2"
+	"strconv"
+	"time"
+)
+
+// 将表格信息转化成指标数据
+func GetBalanceExcelData(excelDetail *excelModel.ExcelInfo, lang string) (newDataMap map[int]map[int]request.MixedTableCellDataReq, allRows, allCols int, err error, errMsg string) {
+	var result request.MixedTableReq
+	err = json.Unmarshal([]byte(excelDetail.Content), &result)
+	if err != nil {
+		err = errors.New("表格json转结构体失败,Err:" + err.Error())
+		return
+	}
+	newData, tmpErr, tmpErrMsg := GetMixedTableCellData(result, lang)
+	if tmpErr != nil {
+		errMsg = "获取失败"
+		if tmpErrMsg != `` {
+			errMsg = tmpErrMsg
+		}
+		err = errors.New("获取最新的数据失败,Err:" + tmpErr.Error())
+		return
+	}
+
+	allRows = len(newData)
+	allCols = 0
+	newDataMap = make(map[int]map[int]request.MixedTableCellDataReq)
+	for r, row := range newData {
+		tmp := len(row)
+		if tmp > allCols {
+			allCols = tmp
+		}
+		colMap := make(map[int]request.MixedTableCellDataReq)
+		for c, col := range row {
+			colMap[c] = col
+		}
+		newDataMap[r] = colMap
+	}
+	return
+}
+
+// GetBalanceExcelEdbData 将表格信息转化成指标数据
+func GetBalanceExcelEdbData(excelEdbMappingItem *excelModel.ExcelChartEdb, newMixedTableCellDataListMap map[int]map[int]request.MixedTableCellDataReq, dataListMap map[int][]*data_manage.EdbDataList, allRows, allCols int) (err error, errMsg string) {
+	var dateList, dataList []string
+	// 日期序列
+	{
+		_, startColumnName, endColumnName, startNum, endNum, isAll, isRow, isColumn, tmpErr := GetSheetStr(excelEdbMappingItem.DateSequence)
+		if tmpErr != nil {
+			err = tmpErr
+			return
+		}
+
+		startNum = startNum - 1
+		endNum = endNum - 1
+		// 选择行的数据
+		if isRow {
+			// 因为是选择一行的数据,所以开始行和结束行时一样的
+			//endNum = startNum - 1
+
+			// 开始列名、结束列
+			var startColumn, endColumn int
+			if isAll {
+				// 结束列(其实也就是整列的个数)
+				endColumn = allCols - 1
+			} else {
+				tmpStartColumn, tmpErr := excelize.ColumnNameToNumber(startColumnName)
+				if tmpErr != nil {
+					errMsg = "列名异常:" + startColumnName
+					err = errors.New(errMsg)
+					return
+				}
+
+				tmpEndColumn, tmpErr := excelize.ColumnNameToNumber(endColumnName)
+				if tmpErr != nil {
+					errMsg = "列名异常:" + endColumnName
+					err = errors.New(errMsg)
+					return
+				}
+				startColumn = tmpStartColumn - 1
+				endColumn = tmpEndColumn - 1
+			}
+
+			// 最大列数,如果设置的超过了最大列数,那么结束列就是最大列数
+			maxCol := allCols
+			if endColumn > maxCol {
+				endColumn = maxCol - 1
+			}
+
+			// 长度固定,避免一直申请内存空间
+			//dateList = make([]string, endColumn-startColumn+1)
+			dateList = make([]string, 0)
+			i := 0
+			for currColumn := startColumn; currColumn <= endColumn; currColumn++ {
+				currCell, ok := newMixedTableCellDataListMap[startNum][currColumn]
+				if !ok {
+					errMsg = fmt.Sprintf("第%d列,第%d行数据异常", currColumn, startNum)
+					err = errors.New(errMsg)
+					return
+				}
+				dateList = append(dateList, currCell.ShowValue)
+				//dateList[i] = currCell.ShowValue
+				i++
+			}
+
+		} else if isColumn { // 选择列的数据
+			if isAll {
+				// 选择一整列的话,结束行得根据实际情况调整(其实也就是整个sheet有多少行)
+				endNum = allRows - 1
+			}
+
+			startColumn, tmpErr := excelize.ColumnNameToNumber(startColumnName)
+			if tmpErr != nil {
+				errMsg = "列名异常:" + startColumnName
+				err = errors.New(errMsg)
+				return
+			}
+			startColumn = startColumn - 1
+
+			// 最大行数,如果设置的超过了最大行数,那么结束行就是最大行数
+			maxRow := allRows
+			if endNum > maxRow {
+				endNum = maxRow - 1
+			}
+			// 长度固定,避免一直申请内存空间
+			//dateList = make([]string, endNum-startNum+1)
+			fmt.Println("startNum:", startNum, "endNum:", endNum)
+			dateList = make([]string, 0)
+			i := 0
+			for currRow := startNum; currRow <= endNum; currRow++ {
+				currCell, ok := newMixedTableCellDataListMap[currRow][startColumn]
+				if !ok {
+					errMsg = fmt.Sprintf("第%d列,第%d行数据异常", currRow, startColumn)
+					err = errors.New(errMsg)
+					return
+				}
+				dateList = append(dateList, currCell.ShowValue)
+				//dateList[i] = currCell.ShowValue
+				i++
+			}
+		}
+
+	}
+
+	// 数据序列
+	{
+		_, startColumnName, endColumnName, startNum, endNum, isAll, isRow, isColumn, tmpErr := GetSheetStr(excelEdbMappingItem.DataSequence)
+		if tmpErr != nil {
+			err = tmpErr
+			return
+		}
+
+		startNum = startNum - 1
+		endNum = endNum - 1
+		// 选择行的数据
+		if isRow {
+			// 开始列名、结束列
+			var startColumn, endColumn int
+			if isAll {
+				// 结束列(其实也就是整列的个数)
+				endColumn = allCols - 1
+			} else {
+
+				tmpStartColumn, tmpErr := excelize.ColumnNameToNumber(startColumnName)
+				if tmpErr != nil {
+					errMsg = "列名异常:" + startColumnName
+					err = errors.New(errMsg)
+					return
+				}
+
+				tmpEndColumn, tmpErr := excelize.ColumnNameToNumber(endColumnName)
+				if tmpErr != nil {
+					errMsg = "列名异常:" + endColumnName
+					err = errors.New(errMsg)
+					return
+				}
+				startColumn = tmpStartColumn - 1
+				endColumn = tmpEndColumn - 1
+			}
+
+			// 最大列数,如果设置的超过了最大列数,那么结束列就是最大列数
+			maxCol := allCols
+			if endColumn > maxCol {
+				endColumn = maxCol - 1
+			}
+			// 长度固定,避免一直申请内存空间
+			//dataList = make([]string, endColumn-startColumn+1)
+			dataList = make([]string, 0)
+			i := 0
+			for currColumn := startColumn; currColumn <= endColumn; currColumn++ {
+				currCell, ok := newMixedTableCellDataListMap[startNum][currColumn]
+				if !ok {
+					errMsg = fmt.Sprintf("第%d列,第%d行数据异常", startColumn, currColumn)
+					err = errors.New(errMsg)
+					return
+				}
+				dataList = append(dataList, currCell.ShowValue)
+				//dataList[i] = currCell.ShowValue
+				i++
+			}
+
+		} else if isColumn { // 选择列的数据
+			if isAll {
+				// 选择一整列的话,结束行得根据实际情况调整(其实也就是整个sheet有多少行)
+				endNum = allRows - 1
+			}
+
+			startColumn, tmpErr := excelize.ColumnNameToNumber(startColumnName)
+			if tmpErr != nil {
+				errMsg = "列名异常:" + startColumnName
+				err = errors.New(errMsg)
+				return
+			}
+			startColumn = startColumn - 1
+
+			// 最大行数,如果设置的超过了最大行数,那么结束行就是最大行数
+			maxRow := allRows
+			if endNum > maxRow {
+				endNum = maxRow - 1
+			}
+
+			// 长度固定,避免一直申请内存空间
+			//dataList = make([]string, endNum-startNum+1)
+			dataList = make([]string, 0)
+			i := 0
+			for currRow := startNum; currRow <= endNum; currRow++ {
+				currCell, ok := newMixedTableCellDataListMap[currRow][startColumn]
+				if !ok {
+					errMsg = fmt.Sprintf("第%d列,第%d行数据异常", currRow, startColumn)
+					err = errors.New(errMsg)
+					return
+				}
+				dataList = append(dataList, currCell.ShowValue)
+				//dataList[i] = currCell.ShowValue
+				i++
+			}
+		}
+	}
+
+	//fmt.Println(dateList, dataList)
+	//fmt.Println("日期序列结束")
+
+	// 将excel中的日期、数据系列处理
+	//newDateList, newDataList, err, errMsg := excel2.HandleEdbSequenceVal(dateList, dataList)
+	newDateList, newDataList := dateList, dataList
+	if err != nil {
+		err = fmt.Errorf(" 处理日期和数据系列失败 %s", err.Error())
+		return
+	}
+	newDataMap := make(map[int]float64, len(newDataList))
+	for i, v := range newDataList {
+		if v != "" {
+			val, e := strconv.ParseFloat(v, 64)
+			if e != nil {
+				err = fmt.Errorf(" 处理日期和数据系列失败 %s", e.Error())
+				return
+			}
+			newDataMap[i] = val
+		}
+	}
+	//组装成excelEdbData
+	list := make([]*data_manage.EdbDataList, 0)
+
+	for i, v := range newDateList {
+		val, ok := newDataMap[i]
+		if !ok {
+			continue
+		}
+		// todo 处理DataTimestamp
+		dataTime, e := time.ParseInLocation(utils.FormatDate, v, time.Local)
+		if e != nil {
+			err = errors.New("time.Parse Err:" + e.Error())
+			return
+		}
+		timestamp := dataTime.UnixNano() / 1e6
+		tmp := &data_manage.EdbDataList{
+			EdbDataId:     i,
+			EdbInfoId:     excelEdbMappingItem.ExcelChartEdbId,
+			DataTime:      v,
+			DataTimestamp: timestamp,
+			Value:         val,
+		}
+		list = append(list, tmp)
+	}
+	dataListMap[excelEdbMappingItem.ExcelChartEdbId] = list
+	return
+}
+
+// 根据chartInfoId获取单个图表信息
+func GetBalanceExcelChartSingle(chartInfoId, ChartEdbId int, lang string) (mappingListTmp []*excelModel.ExcelChartEdb, dataListMap map[int][]*data_manage.EdbDataList, err error, errMsg string) {
+	// 相关联指标
+	if chartInfoId == 0 && ChartEdbId == 0 {
+		err = fmt.Errorf(" 获取图表,指标信息失败 Err:chartInfoId和ChartEdbId不能同时为空")
+		return
+	}
+	if chartInfoId == 0 {
+		chartEdb, e := excelModel.GetExcelChartEdbById(ChartEdbId)
+		if e != nil {
+			err = fmt.Errorf(" 获取图表,指标信息失败 Err:%s", e.Error())
+			return
+		}
+		chartInfoId = chartEdb.ChartInfoId
+	}
+	mappingListTmp, err = excelModel.GetExcelChartEdbMappingByChartInfoId(chartInfoId)
+	if err != nil {
+		errMsg = "获取失败"
+		err = fmt.Errorf(" 获取图表,指标信息失败 Err:%s", err.Error())
+		return
+	}
+	if len(mappingListTmp) <= 0 {
+		errMsg = "获取失败"
+		err = fmt.Errorf(" 获取图表,指标信息失败 Err:%s", err.Error())
+		return
+	}
+	// 查询所有子表
+	excelInfoId := mappingListTmp[0].ExcelInfoId
+	excelInfo, err := excelModel.GetExcelInfoById(excelInfoId)
+	if err != nil {
+		if err.Error() == utils.ErrNoRow() {
+			errMsg = "表格不存在"
+			err = fmt.Errorf(errMsg)
+			return
+		}
+		errMsg = "查询子表失败"
+		err = fmt.Errorf(" 查询子表失败图表,指标信息失败 Err:%s", err.Error())
+		return
+	}
+	dataListMap = make(map[int][]*data_manage.EdbDataList)
+	if excelInfo.BalanceType == 1 {
+		//查询库里是否有值
+		chartDataList, e := excelModel.GetExcelChartDataByChartInfoId(chartInfoId)
+		if e != nil {
+			err = fmt.Errorf(" 获取图表,指标信息失败 Err:%s", e.Error())
+			return
+		}
+		if len(chartDataList) == 0 {
+			err = fmt.Errorf(" 获取图表,指标数据不存在")
+			return
+		}
+		for _, v := range chartDataList {
+			tmp := &data_manage.EdbDataList{
+				EdbDataId:     v.ExcelChartDataId,
+				EdbInfoId:     v.ExcelChartEdbId,
+				DataTime:      v.DataTime,
+				DataTimestamp: v.DataTimestamp,
+				Value:         v.Value,
+			}
+			dataListMap[v.ExcelChartEdbId] = append(dataListMap[v.ExcelChartEdbId], tmp)
+		}
+		return
+	}
+
+	// 获取图表详情
+	newExcelDataMap, excelAllRows, excelAllCols, err, errMsg := GetBalanceExcelData(excelInfo, lang)
+	if err != nil {
+		return
+	}
+
+	for _, mapping := range mappingListTmp {
+		er, msg := GetBalanceExcelEdbData(mapping, newExcelDataMap, dataListMap, excelAllRows, excelAllCols)
+		if er != nil {
+			utils.FileLog.Info(fmt.Sprintf(" 获取图表,指标信息失败 Err:%s, %s", er.Error(), msg))
+			continue
+		}
+	}
+	return
+}
+
+// GetBalanceExcelInfoOpButton 获取ETA平衡表格的操作权限
+func GetBalanceExcelInfoOpButton(sysUserId, parentSysUserId int, haveOperaAuth bool, parentExcelInfoId int) (button excelModel.ExcelInfoDetailButton) {
+	// 如果没有数据权限,那么直接返回
+	if !haveOperaAuth {
+		return
+	}
+	//非管理员角色查看其他用户创建的表格,可刷新、另存为、下载表格;
+	button.RefreshButton = true
+	button.CopyButton = true
+	button.DownloadButton = true
+
+	if sysUserId == parentSysUserId {
+		button.OpButton = true
+		button.RefreshEdbButton = true
+		button.OpWorkerButton = true
+		button.DeleteButton = true
+	} else {
+		obj := new(excelModel.ExcelWorker)
+		workerList, err := obj.GetByExcelInfoId(parentExcelInfoId)
+		if err == nil {
+			for _, v := range workerList {
+				if v.SysUserId == sysUserId {
+					button.OpButton = true
+					button.RefreshEdbButton = true
+					button.DeleteButton = true
+					break
+				}
+			}
+		}
+	}
+	return
+}

+ 106 - 3
services/data/excel/excel_info.go

@@ -3,6 +3,7 @@ package excel
 import (
 	"encoding/json"
 	"errors"
+	"eta/eta_mobile/models"
 	"eta/eta_mobile/models/data_manage"
 	"eta/eta_mobile/models/data_manage/excel"
 	"eta/eta_mobile/models/data_manage/excel/request"
@@ -55,8 +56,27 @@ func GetExcelDetailInfoByUnicode(unicode string, sysUserId int, lang string) (ex
 }
 
 func formatExcelInfo2Detail(excelInfo *excel.ExcelInfo, sysUserId int, lang string) (excelDetail response.ExcelInfoDetail, errMsg string, err error) {
+	checkExcelInfo := excelInfo
+	if excelInfo.Source == utils.BALANCE_TABLE {
+		checkExcelInfoId := excelInfo.ExcelInfoId
+		if excelInfo.BalanceType == 1 {
+			checkExcelInfoId = excelInfo.RelExcelInfoId
+		} else {
+			if excelInfo.ParentId > 0 {
+				checkExcelInfoId = excelInfo.ParentId
+			}
+		}
+		if checkExcelInfoId != excelInfo.ExcelInfoId {
+			checkExcelInfo, err = excel.GetExcelInfoById(checkExcelInfoId)
+			if err != nil {
+				errMsg = "获取平衡表格信息失败"
+				err = errors.New("获取平衡表格信息失败,Err:" + err.Error())
+				return
+			}
+		}
+	}
 	// 数据权限
-	haveOperaAuth, err := data_manage_permission.CheckExcelPermissionByExcelInfoId(excelInfo.ExcelInfoId, excelInfo.ExcelClassifyId, excelInfo.IsJoinPermission, sysUserId)
+	haveOperaAuth, err := data_manage_permission.CheckExcelPermissionByExcelInfoId(checkExcelInfo.ExcelInfoId, checkExcelInfo.ExcelClassifyId, checkExcelInfo.IsJoinPermission, sysUserId)
 	if err != nil {
 		err = errors.New("获取表格权限信息失败,Err" + err.Error())
 		return
@@ -80,6 +100,7 @@ func formatExcelInfo2Detail(excelInfo *excel.ExcelInfo, sysUserId int, lang stri
 		CreateTime:      excelInfo.CreateTime,
 		TableData:       nil,
 		HaveOperaAuth:   haveOperaAuth,
+		SourcesFrom:     excelInfo.SourcesFrom,
 	}
 
 	// 无权限,不需要返回数据
@@ -132,7 +153,13 @@ func formatExcelInfo2Detail(excelInfo *excel.ExcelInfo, sysUserId int, lang stri
 				}
 			}
 		}
-
+		sourceNameList, sourceNameEnList, e := GetEdbSourceByEdbInfoIdList(result.EdbInfoIdList)
+		if e != nil {
+			err = errors.New("自定义表格数据获取失败,Err:" + e.Error())
+			return
+		}
+		excelDetail.ExcelSource = strings.Join(sourceNameList, ",")
+		excelDetail.ExcelSourceEn = strings.Join(sourceNameEnList, ",")
 		excelDetail.TableData = result
 	case utils.MIXED_TABLE: // 混合表格
 		var result request.MixedTableReq
@@ -152,12 +179,35 @@ func formatExcelInfo2Detail(excelInfo *excel.ExcelInfo, sysUserId int, lang stri
 		}
 		result.Data = newData
 		excelDetail.TableData = result
+
+		edbInfoIds := make([]int, 0)
+		edbInfoIdExist := make(map[int]bool)
+		if len(result.Data) > 0 {
+			for _, t := range result.Data {
+				for _, v := range t {
+					if v.EdbInfoId > 0 && !edbInfoIdExist[v.EdbInfoId] {
+						edbInfoIdExist[v.EdbInfoId] = true
+						edbInfoIds = append(edbInfoIds, v.EdbInfoId)
+					}
+				}
+			}
+		}
+		sourceNameList, sourceNameEnList, e := GetEdbSourceByEdbInfoIdList(edbInfoIds)
+		if e != nil {
+			err = errors.New("自定义表格数据获取失败,Err:" + e.Error())
+			return
+		}
+		excelDetail.ExcelSource = strings.Join(sourceNameList, ",")
+		excelDetail.ExcelSourceEn = strings.Join(sourceNameEnList, ",")
+	}
+	if excelDetail.Source == utils.BALANCE_TABLE {
+		excelDetail.Button = GetBalanceExcelInfoOpButton(sysUserId, checkExcelInfo.SysUserId, excelDetail.HaveOperaAuth, checkExcelInfo.ExcelInfoId)
 	}
 	return
 }
 
 // GetExcelInfoOpButton 获取ETA表格的操作权限
-func GetExcelInfoOpButton(sysUser *system.Admin, belongUserId, source int, haveOperaAuth bool) (button response.ExcelInfoDetailButton) {
+func GetExcelInfoOpButton(sysUser *system.Admin, belongUserId, source int, haveOperaAuth bool) (button excel.ExcelInfoDetailButton) {
 	// 如果没有数据权限,那么直接返回
 	if !haveOperaAuth {
 		return
@@ -1405,3 +1455,56 @@ func GetExcelEdbBatchRefreshKey(source string, reportId, chapterId int) string {
 
 	return fmt.Sprint("batch_refresh_excel_edb:", source, ":", reportId, ":", chapterId)
 }
+
+
+// GetEdbSourceByEdbInfoIdList 获取关联指标的来源
+func GetEdbSourceByEdbInfoIdList(edbInfoIdList []int) (sourceNameList, sourceNameEnList []string,err error) {
+	sourceNameList = make([]string, 0)
+	sourceNameEnList = make([]string, 0)
+	sourceMap := make(map[int]string)
+	edbInfoList, tmpErr := data_manage.GetEdbInfoByIdList(edbInfoIdList)
+	if tmpErr != nil {
+		err = tmpErr
+		return
+	}
+	for _, v := range edbInfoList {
+		// 指标类型:1:基础指标,2:计算指标
+		if v.EdbType == 2 {
+			//sourceMap[0] = "弘则研究"
+			baseEdbInfoArr, _, _ := data_manage.GetRefreshEdbInfoFromBase(v.EdbInfoId, v.Source)
+			for _, baseEdbInfo := range baseEdbInfoArr {
+				if baseEdbInfo.EdbInfoType == 0 { //普通指标才参与,预测指标不参与
+					sourceMap[baseEdbInfo.Source] = baseEdbInfo.SourceName
+				}
+			}
+		} else {
+			sourceMap[v.Source] = v.SourceName
+		}
+	}
+
+	for source, sourceName := range sourceMap {
+		if utils.InArrayByInt([]int{utils.DATA_SOURCE_MANUAL, utils.DATA_SOURCE_MYSTEEL_CHEMICAL}, source) {
+			continue
+		}
+		sourceNameList = append(sourceNameList, sourceName)
+
+		sourceNameEn, ok := utils.DataSourceEnMap[source]
+		if !ok {
+			sourceNameEn = sourceName
+		}
+		sourceNameEnList = append(sourceNameEnList, sourceNameEn)
+	}
+	//sourceNameList = append(sourceNameList, utils.ChartDefaultNameCn)
+	//sourceNameEnList = append(sourceNameEnList, utils.ChartDefaultNameEn)
+
+	// 图表来源
+	conf, e := models.GetBusinessConf()
+	if e != nil {
+		return
+	}
+	if conf[models.BusinessConfCompanyName] != "" {
+		sourceNameList = append(sourceNameList, conf[models.BusinessConfCompanyName])
+		sourceNameEnList = append(sourceNameEnList, conf[models.BusinessConfCompanyName])
+	}
+	return
+}

+ 55 - 0
services/data/factor_edb_series.go

@@ -0,0 +1,55 @@
+package data
+
+import (
+	"encoding/json"
+	"eta/eta_mobile/models"
+	"eta/eta_mobile/utils"
+	"fmt"
+)
+
+// PostRefreshFactorEdbRecalculate 因子指标重计算
+func PostRefreshFactorEdbRecalculate(edbInfoId int, edbCode string) (resp *models.BaseResponse, err error) {
+	param := make(map[string]interface{})
+	param["EdbInfoId"] = edbInfoId
+	param["EdbCode"] = edbCode
+	postUrl := fmt.Sprintf("%s%s", utils.EDB_LIB_URL, "factor_edb_series/recalculate")
+	postData, e := json.Marshal(param)
+	if e != nil {
+		err = fmt.Errorf("param json err: %v", e)
+		return
+	}
+	result, e := HttpPost(postUrl, string(postData), utils.ZhLangVersion, "application/json")
+	if e != nil {
+		err = fmt.Errorf("http post err: %v", e)
+		return
+	}
+	utils.FileLog.Info("PostRefreshFactorEdbRecalculate:" + postUrl + ";" + string(postData) + ";result:" + string(result))
+	if e = json.Unmarshal(result, &resp); e != nil {
+		err = fmt.Errorf("resp unmarshal err: %v", e)
+		return
+	}
+	return
+}
+
+// PostRefreshFactorEdbChartRecalculate 因子指标图表重计算
+func PostRefreshFactorEdbChartRecalculate(chartInfoId int) (resp *models.BaseResponse, err error) {
+	param := make(map[string]interface{})
+	param["ChartInfoId"] = chartInfoId
+	postUrl := fmt.Sprintf("%s%s", utils.EDB_LIB_URL, "factor_edb_series/chart_recalculate")
+	postData, e := json.Marshal(param)
+	if e != nil {
+		err = fmt.Errorf("param json err: %v", e)
+		return
+	}
+	result, e := HttpPost(postUrl, string(postData), utils.ZhLangVersion, "application/json")
+	if e != nil {
+		err = fmt.Errorf("http post err: %v", e)
+		return
+	}
+	utils.FileLog.Info("PostRefreshFactorEdbChartRecalculate:" + postUrl + ";" + string(postData) + ";result:" + string(result))
+	if e = json.Unmarshal(result, &resp); e != nil {
+		err = fmt.Errorf("resp unmarshal err: %v", e)
+		return
+	}
+	return
+}

+ 58 - 14
services/data/future_good/chart_info.go

@@ -376,13 +376,27 @@ func GetChartEdbData(chartInfoId int, startDate, endDate string, edbInfoMapping,
 // BarChartData 获取数据
 func BarChartData(edbInfoMapping *data_manage.ChartEdbInfoMapping, futureGoodMappingList []*future_good2.FutureGoodEdbInfo, edbDataListMap map[int][]*data_manage.EdbDataList, barChartInfoDateList []data_manage.BarChartInfoDateReq, regionType, latestDate string) (edbIdList []int, yDataList []data_manage.YData, err error) {
 	// 指标数据数组(10086:{"2022-12-02":100.01,"2022-12-01":102.3})
-	edbDataMap := make(map[int]map[string]float64)
+	// 现货指标数据map
+	baseEdbDataMap := make(map[string]float64)
 	for edbInfoId, edbDataList := range edbDataListMap {
+		if edbInfoId == edbInfoMapping.EdbInfoId {
+			for _, edbData := range edbDataList {
+				baseEdbDataMap[edbData.DataTime] = edbData.Value
+			}
+		}
+	}
+
+	// 期货指标数据map
+	futureGoodEdbDataMap := make(map[int]map[string]float64)
+	for edbInfoId, edbDataList := range edbDataListMap {
+		if edbInfoId == edbInfoMapping.EdbInfoId {
+			continue
+		}
 		edbDateData := make(map[string]float64)
 		for _, edbData := range edbDataList {
 			edbDateData[edbData.DataTime] = edbData.Value
 		}
-		edbDataMap[edbInfoId] = edbDateData
+		futureGoodEdbDataMap[edbInfoId] = edbDateData
 	}
 
 	// edbIdList 指标展示顺序;x轴的指标顺序
@@ -429,7 +443,7 @@ func BarChartData(edbInfoMapping *data_manage.ChartEdbInfoMapping, futureGoodMap
 		xEdbInfoIdList := make([]int, 0)    // 当前数据的指标id列表
 
 		// 现货指标
-		realDateTime, findDataValue, isFind, tmpErr := GetNeedDateData(findDateTime, edbDataListMap[edbInfoMapping.EdbInfoId], edbDataMap[edbInfoMapping.EdbInfoId])
+		realDateTime, findDataValue, isFind, tmpErr := GetNeedDateData(findDateTime, edbDataListMap[edbInfoMapping.EdbInfoId], baseEdbDataMap, futureGoodEdbDataMap)
 		if tmpErr != nil {
 			err = tmpErr
 			return
@@ -442,8 +456,13 @@ func BarChartData(edbInfoMapping *data_manage.ChartEdbInfoMapping, futureGoodMap
 			noDataIdList = append(noDataIdList, edbInfoMapping.EdbInfoId)
 			noDataIdMap[edbInfoMapping.EdbInfoId] = edbInfoMapping.EdbInfoId
 		}
-		currMonth := findDateTime.Month() // 当前月份
-		currYear := findDateTime.Year()   // 当前年份
+		//currMonth := findDateTime.Month() // 当前月份
+		//currYear := findDateTime.Year()   // 当前年份
+
+		// 用实际日期的月份作为基准,往前推12个月(2024-5-13 16:26:43修改)
+		currMonth := realDateTime.Month() // 当前月份
+		currYear := realDateTime.Year()   // 当前年份
+
 		xEdbInfoIdList = append(xEdbInfoIdList, edbInfoMapping.EdbInfoId)
 		mList := make([]int, 0) // 间隔月份
 		indexList := make([]int, 0)
@@ -482,7 +501,7 @@ func BarChartData(edbInfoMapping *data_manage.ChartEdbInfoMapping, futureGoodMap
 			//}
 			//tmpRealDateTime := findDateTime	// 按照配置找到的日期
 			tmpRealDateTime := realDateTime // 实际现货的日期
-			tmpFindDataValue, tmpIsFind := edbDataMap[futureGoodMapping.FutureGoodEdbInfoId][tmpRealDateTime.Format(utils.FormatDate)]
+			tmpFindDataValue, tmpIsFind := futureGoodEdbDataMap[futureGoodMapping.FutureGoodEdbInfoId][tmpRealDateTime.Format(utils.FormatDate)]
 			yDataMap[futureGoodMapping.FutureGoodEdbInfoId] = tmpFindDataValue
 
 			findDataList = append(findDataList, tmpFindDataValue)
@@ -860,7 +879,7 @@ func getFutureGoodEdbInfoList(latestDateTime time.Time, tmpFutureGoodEdbInfoList
 }
 
 // GetNeedDateData 获取合约内需要的日期数据
-func GetNeedDateData(needDateTime time.Time, dataList []*data_manage.EdbDataList, edbDataMap map[string]float64) (findDateTime time.Time, findDataValue float64, isFind bool, err error) {
+func GetNeedDateData(needDateTime time.Time, dataList []*data_manage.EdbDataList, edbDataMap map[string]float64, allEdbDataMap map[int]map[string]float64) (findDateTime time.Time, findDataValue float64, isFind bool, err error) {
 	//dataList := edbDataListMap[edbInfoId] //指标的所有数据值
 	if len(dataList) <= 0 {
 		// 没有数据的指标id
@@ -873,18 +892,43 @@ func GetNeedDateData(needDateTime time.Time, dataList []*data_manage.EdbDataList
 		return
 	}
 
+	// 该日期存在数据的期货指标的最小数量,目前是现货和期货各1个,总共2个
+	maxCount := 1
+
 	for tmpDateTime := needDateTime; tmpDateTime.After(minDateTime) || tmpDateTime.Equal(minDateTime); tmpDateTime = tmpDateTime.AddDate(0, 0, -1) {
 		tmpDate := tmpDateTime.Format(utils.FormatDate)
-		if tmpValue, ok := edbDataMap[tmpDate]; ok { //如果能找到数据,那么就返回
-			// 数据为0,也直接返回,做无值处理
-			if tmpValue == 0 {
-				return
+		tmpValue, ok := edbDataMap[tmpDate]
+		if !ok {
+			continue
+		}
+
+		// 该日期存在数据的指标数量
+		count := 0
+
+		for _, currEdbDataMap := range allEdbDataMap {
+			_, tmpIsFind := currEdbDataMap[tmpDate]
+			if tmpIsFind {
+				count++
+				if count >= maxCount {
+					continue
+				}
 			}
-			findDateTime, _ = time.ParseInLocation(utils.FormatDate, tmpDate, time.Local)
-			findDataValue = tmpValue
-			isFind = true
+		}
+
+		// 该日期存在数据的期货指标数量小于2个,那么要继续往前找
+		if count < maxCount {
+			continue
+		}
+
+		//如果能找到数据,那么就返回
+		// 数据为0,也直接返回,做无值处理
+		if tmpValue == 0 {
 			return
 		}
+		findDateTime, _ = time.ParseInLocation(utils.FormatDate, tmpDate, time.Local)
+		findDataValue = tmpValue
+		isFind = true
+		return
 	}
 
 	return

+ 4 - 2
services/data/future_good/profit_chart_info.go

@@ -248,7 +248,7 @@ func ProfitChartChartData(baseDataList []*data_manage.EdbDataList, futureGoodEdb
 		xEdbInfoIdList := make([]int, 0)   // 当前数据的指标id列表
 
 		// 现货指标
-		realDateTime, findDataValue, isFind, tmpErr := GetNeedDateData(findDateTime, baseDataList, baseEdbDateData)
+		realDateTime, findDataValue, isFind, tmpErr := GetNeedDateData(findDateTime, baseDataList, baseEdbDateData, edbDataMap)
 		if tmpErr != nil {
 			err = tmpErr
 			return
@@ -274,7 +274,9 @@ func ProfitChartChartData(baseDataList []*data_manage.EdbDataList, futureGoodEdb
 			//findDateTime
 
 			// 获取当前日期相对开始日期的期数
-			tmpN := (currDate.Year()-findDateTime.Year())*12 + int(currDate.Month()-findDateTime.Month())
+			//tmpN := (currDate.Year()-findDateTime.Year())*12 + int(currDate.Month()-findDateTime.Month())
+			// 用实际日期的月份作为基准,往前推12个月(2024-5-13 16:26:43修改)
+			tmpN := (currDate.Year()-realDateTime.Year())*12 + int(currDate.Month()-realDateTime.Month())
 			if tmpN <= 0 {
 				continue
 			}

+ 190 - 32
services/elastic/elastic.go

@@ -333,6 +333,35 @@ func SearchEdbInfoData(indexName, keywordStr string, from, size, filterSource, s
 	//})
 
 	//关键字匹配
+	//shouldMap := map[string]interface{}{
+	//	"should": []interface{}{
+	//		map[string]interface{}{
+	//			"match": map[string]interface{}{
+	//				"EdbCode": keywordStr,
+	//				//"Frequency.keyword": "月度",
+	//			},
+	//		},
+	//		map[string]interface{}{
+	//			"match": map[string]interface{}{
+	//				"EdbName": keywordStr,
+	//				//"Frequency.keyword": "月度",
+	//			},
+	//		},
+	//		map[string]interface{}{
+	//			"match": map[string]interface{}{
+	//				"EdbNameEn": keywordStr,
+	//				//"Frequency.keyword": "月度",
+	//			},
+	//		},
+	//	},
+	//}
+
+	// 默认使用中文名字字段去匹配
+	keywordNameKey := `EdbName`
+	// 如果没有中文,则使用英文名称字段去匹配
+	if !utils.ContainsChinese(keywordStr) {
+		keywordNameKey = `EdbNameEn`
+	}
 	shouldMap := map[string]interface{}{
 		"should": []interface{}{
 			map[string]interface{}{
@@ -343,21 +372,16 @@ func SearchEdbInfoData(indexName, keywordStr string, from, size, filterSource, s
 			},
 			map[string]interface{}{
 				"match": map[string]interface{}{
-					"EdbName": keywordStr,
-					//"Frequency.keyword": "月度",
-				},
-			},
-			map[string]interface{}{
-				"match": map[string]interface{}{
-					"EdbNameEn": keywordStr,
+					keywordNameKey: keywordStr,
 					//"Frequency.keyword": "月度",
 				},
 			},
 		},
 	}
-	mustMap = append(mustMap, map[string]interface{}{
-		"bool": shouldMap,
-	})
+
+	//mustMap = append(mustMap, map[string]interface{}{
+	//	"bool": shouldMap,
+	//})
 
 	return searchEdbInfoData(indexName, mustMap, mustNotMap, shouldMap, from, size)
 }
@@ -697,6 +721,35 @@ func SearchAddPredictEdbInfoData(indexName, keywordStr string, noPermissionEdbIn
 	})
 
 	//关键字匹配
+	//shouldMap := map[string]interface{}{
+	//	"should": []interface{}{
+	//		map[string]interface{}{
+	//			"match": map[string]interface{}{
+	//				"EdbCode": keywordStr,
+	//				//"Frequency.keyword": "月度",
+	//			},
+	//		},
+	//		map[string]interface{}{
+	//			"match": map[string]interface{}{
+	//				"EdbName": keywordStr,
+	//				//"Frequency.keyword": "月度",
+	//			},
+	//		},
+	//		map[string]interface{}{
+	//			"match": map[string]interface{}{
+	//				"EdbNameEn": keywordStr,
+	//				//"Frequency.keyword": "月度",
+	//			},
+	//		},
+	//	},
+	//}
+
+	// 默认使用中文名字字段去匹配
+	keywordNameKey := `EdbName`
+	// 如果没有中文,则使用英文名称字段去匹配
+	if !utils.ContainsChinese(keywordStr) {
+		keywordNameKey = `EdbNameEn`
+	}
 	shouldMap := map[string]interface{}{
 		"should": []interface{}{
 			map[string]interface{}{
@@ -707,7 +760,7 @@ func SearchAddPredictEdbInfoData(indexName, keywordStr string, noPermissionEdbIn
 			},
 			map[string]interface{}{
 				"match": map[string]interface{}{
-					"EdbName": keywordStr,
+					keywordNameKey: keywordStr,
 					//"Frequency.keyword": "月度",
 				},
 			},
@@ -1211,34 +1264,61 @@ func SearchChartInfoData(indexName, keywordStr string, showSysId int, sourceList
 	})
 
 	//关键字匹配
+	//shouldMap := map[string]interface{}{
+	//	"should": []interface{}{
+	//		map[string]interface{}{
+	//			"match": map[string]interface{}{
+	//				"ChartName": keywordStr,
+	//				//"Frequency.keyword": "月度",
+	//			},
+	//		},
+	//		// 因为关键词被分了,所以需要用下面的语句来让他 整个词 查询,从而加重整词的权重
+	//		map[string]interface{}{
+	//			"match": map[string]interface{}{
+	//				"ChartName": map[string]interface{}{
+	//					"query":    keywordStr,
+	//					"operator": "and",
+	//				},
+	//				//"Frequency.keyword": "月度",
+	//			},
+	//		},
+	//		map[string]interface{}{
+	//			"match": map[string]interface{}{
+	//				"ChartNameEn": keywordStr,
+	//				//"Frequency.keyword": "月度",
+	//			},
+	//		},
+	//		// 因为关键词被分了,所以需要用下面的语句来让他 整个词 查询,从而加重整词的权重
+	//		map[string]interface{}{
+	//			"match": map[string]interface{}{
+	//				"ChartNameEn": map[string]interface{}{
+	//					"query":    keywordStr,
+	//					"operator": "and",
+	//				},
+	//				//"Frequency.keyword": "月度",
+	//			},
+	//		},
+	//	},
+	//}
+
+	// 默认使用中文名字字段去匹配
+	keywordNameKey := `ChartName`
+	// 如果没有中文,则使用英文名称字段去匹配
+	if !utils.ContainsChinese(keywordStr) {
+		keywordNameKey = `ChartNameEn`
+	}
 	shouldMap := map[string]interface{}{
 		"should": []interface{}{
 			map[string]interface{}{
 				"match": map[string]interface{}{
-					"ChartName": keywordStr,
-					//"Frequency.keyword": "月度",
-				},
-			},
-			// 因为关键词被分了,所以需要用下面的语句来让他 整个词 查询,从而加重整词的权重
-			map[string]interface{}{
-				"match": map[string]interface{}{
-					"ChartName": map[string]interface{}{
-						"query":    keywordStr,
-						"operator": "and",
-					},
-					//"Frequency.keyword": "月度",
-				},
-			},
-			map[string]interface{}{
-				"match": map[string]interface{}{
-					"ChartNameEn": keywordStr,
+					keywordNameKey: keywordStr,
 					//"Frequency.keyword": "月度",
 				},
 			},
 			// 因为关键词被分了,所以需要用下面的语句来让他 整个词 查询,从而加重整词的权重
 			map[string]interface{}{
 				"match": map[string]interface{}{
-					"ChartNameEn": map[string]interface{}{
+					keywordNameKey: map[string]interface{}{
 						"query":    keywordStr,
 						"operator": "and",
 					},
@@ -1247,6 +1327,7 @@ func SearchChartInfoData(indexName, keywordStr string, showSysId int, sourceList
 			},
 		},
 	}
+
 	mustMap = append(mustMap, map[string]interface{}{
 		"bool": shouldMap,
 	})
@@ -1394,18 +1475,62 @@ func SearchMyChartInfoData(indexName, keywordStr string, adminId int, noPermissi
 	}
 
 	//关键字匹配
+
+	//shouldMap := map[string]interface{}{
+	//	"should": []interface{}{
+	//		map[string]interface{}{
+	//			"match": map[string]interface{}{
+	//				"ChartName": keywordStr,
+	//				//"Frequency.keyword": "月度",
+	//			},
+	//		},
+	//		// 因为关键词被分了,所以需要用下面的语句来让他 整个词 查询,从而加重整词的权重
+	//		map[string]interface{}{
+	//			"match": map[string]interface{}{
+	//				"ChartName": map[string]interface{}{
+	//					"query":    keywordStr,
+	//					"operator": "and",
+	//				},
+	//				//"Frequency.keyword": "月度",
+	//			},
+	//		},
+	//		map[string]interface{}{
+	//			"match": map[string]interface{}{
+	//				"ChartNameEn": keywordStr,
+	//				//"Frequency.keyword": "月度",
+	//			},
+	//		},
+	//		// 因为关键词被分了,所以需要用下面的语句来让他 整个词 查询,从而加重整词的权重
+	//		map[string]interface{}{
+	//			"match": map[string]interface{}{
+	//				"ChartNameEn": map[string]interface{}{
+	//					"query":    keywordStr,
+	//					"operator": "and",
+	//				},
+	//				//"Frequency.keyword": "月度",
+	//			},
+	//		},
+	//	},
+	//}
+
+	// 默认使用中文名字字段去匹配
+	keywordNameKey := `ChartName`
+	// 如果没有中文,则使用英文名称字段去匹配
+	if !utils.ContainsChinese(keywordStr) {
+		keywordNameKey = `ChartNameEn`
+	}
 	shouldMap := map[string]interface{}{
 		"should": []interface{}{
 			map[string]interface{}{
 				"match": map[string]interface{}{
-					"ChartName": keywordStr,
+					keywordNameKey: keywordStr,
 					//"Frequency.keyword": "月度",
 				},
 			},
 			// 因为关键词被分了,所以需要用下面的语句来让他 整个词 查询,从而加重整词的权重
 			map[string]interface{}{
 				"match": map[string]interface{}{
-					"ChartName": map[string]interface{}{
+					keywordNameKey: map[string]interface{}{
 						"query":    keywordStr,
 						"operator": "and",
 					},
@@ -1414,6 +1539,7 @@ func SearchMyChartInfoData(indexName, keywordStr string, adminId int, noPermissi
 			},
 		},
 	}
+
 	mustMap = append(mustMap, map[string]interface{}{
 		"bool": shouldMap,
 	})
@@ -1624,6 +1750,14 @@ func SearchEdbInfoDataByAdminId(indexName, keywordStr string, from, size, filter
 				},
 			},
 		}
+	case 6:
+		mustNotMap = []interface{}{
+			map[string]interface{}{
+				"match": map[string]interface{}{
+					"Frequency.keyword": "年度",
+				},
+			},
+		}
 	}
 
 	//指标来源
@@ -1661,6 +1795,29 @@ func SearchEdbInfoDataByAdminId(indexName, keywordStr string, from, size, filter
 	//})
 
 	//关键字匹配
+	//shouldMap := map[string]interface{}{
+	//	"should": []interface{}{
+	//		map[string]interface{}{
+	//			"match": map[string]interface{}{
+	//				"EdbCode": keywordStr,
+	//				//"Frequency.keyword": "月度",
+	//			},
+	//		},
+	//		map[string]interface{}{
+	//			"match": map[string]interface{}{
+	//				"EdbName": keywordStr,
+	//				//"Frequency.keyword": "月度",
+	//			},
+	//		},
+	//	},
+	//}
+
+	// 默认使用中文名字字段去匹配
+	keywordNameKey := `EdbName`
+	// 如果没有中文,则使用英文名称字段去匹配
+	if !utils.ContainsChinese(keywordStr) {
+		keywordNameKey = `EdbNameEn`
+	}
 	shouldMap := map[string]interface{}{
 		"should": []interface{}{
 			map[string]interface{}{
@@ -1671,12 +1828,13 @@ func SearchEdbInfoDataByAdminId(indexName, keywordStr string, from, size, filter
 			},
 			map[string]interface{}{
 				"match": map[string]interface{}{
-					"EdbName": keywordStr,
+					keywordNameKey: keywordStr,
 					//"Frequency.keyword": "月度",
 				},
 			},
 		},
 	}
+
 	mustMap = append(mustMap, map[string]interface{}{
 		"bool": shouldMap,
 	})

+ 18 - 3
services/excel/lucky_sheet.go

@@ -1685,7 +1685,7 @@ func GetTableDataByCustomData(excelType int, data request.TableDataReq) (selfTab
 }
 
 // GetTableDataByMixedTableData 通过混合表格数据获取表格数据
-func GetTableDataByMixedTableData(config [][]request.MixedTableCellDataReq) (selfTableData TableData, err error) {
+func GetTableDataByMixedTableData(config [][]request.MixedTableCellDataReq, hideMerged bool) (selfTableData TableData, err error) {
 	tableDataList := make([][]LuckySheetDataValue, 0)
 	mergeList := make([]TableDataMerge, 0)
 
@@ -1694,11 +1694,26 @@ func GetTableDataByMixedTableData(config [][]request.MixedTableCellDataReq) (sel
 		for _, row := range config {
 			dataCol := make([]LuckySheetDataValue, 0)
 			for _, cell := range row {
-				dataCol = append(dataCol, LuckySheetDataValue{
+				tmp := LuckySheetDataValue{
 					Value:     cell.Value,
 					Monitor:   cell.ShowValue,
 					MergeCell: LuckySheetDataConfigMerge{},
-				})
+				}
+				// 前端需要隐藏被合并的单元格, 混合表格/平衡表通过这个字段判断, 不通过HandleTableCell方法隐藏
+				if cell.MerData != nil {
+					if hideMerged && cell.MerData.Type == "merged" {
+						continue
+					}
+					tmp.MergeCell.Rs = cell.MerData.Mer.Rowspan
+					tmp.MergeCell.Cs = cell.MerData.Mer.Colspan
+					tmp.MergeCell.Row = cell.MerData.Mer.Row
+					tmp.MergeCell.Column = cell.MerData.Mer.Col
+				}
+				if cell.ShowStyle != "" {
+					showFormatValue := fmt.Sprintf("%v", cell.ShowFormatValue)
+					tmp.Monitor = showFormatValue
+				}
+				dataCol = append(dataCol, tmp)
 			}
 			tableDataList = append(tableDataList, dataCol)
 		}

+ 59 - 19
services/smart_report.go

@@ -139,23 +139,27 @@ import asyncio
 from pyppeteer import launch
 
 @asyncio.coroutine
-def main():
+async def main():
     # 异步代码
-    browser = yield from launch({
+    browser = await launch({
         'executablePath': '%s',
         'headless': True,
         'args': ['--disable-infobars', '--no-sandbox']
     })
-    page = yield from browser.newPage()
-    yield from page.setViewport({
+    page = await browser.newPage()
+    await page.setViewport({
         'width': 1920,
         'height': 1080,
     })
-    yield from page.goto('%s', {
+    await page.goto('%s', {
         'waitUntil': 'networkidle0',
         'timeout': 1000000  # 设置超时时间为 100 秒
     })
-    yield from page.pdf({
+
+    # 在生成PDF之前等待2秒
+    await asyncio.sleep(5)
+
+    await page.pdf({
         'path': "%s",
         'printBackground': True,
         'format': "A2",
@@ -166,7 +170,7 @@ def main():
             'right': '10mm'
         }
     })
-    yield from browser.close()
+    await browser.close()
 
 # 创建事件循环
 loop = asyncio.get_event_loop()
@@ -182,10 +186,13 @@ finally:
 	pyCode = fmt.Sprintf(pyCode, utils.ChromePath, reportUrl, filePath)
 	utils.FileLog.Info("pdf pyCode: \n" + pyCode)
 	cmd := exec.Command("python3", "-c", pyCode)
-	_, err = cmd.CombinedOutput()
-	if err != nil {
+	output, e := cmd.CombinedOutput()
+	if e != nil {
+		err = e
 		utils.FileLog.Info("ReportToPdf failed: , error: \n" + err.Error())
+		utils.FileLog.Info("Output: %s\n", string(output))
 		go alarm_msg.SendAlarmMsg("ReportToPdf failed:"+err.Error(), 3)
+		go alarm_msg.SendAlarmMsg("Output :"+string(output), 3)
 	}
 	defer func() {
 		cmd.Process.Kill()
@@ -193,7 +200,7 @@ finally:
 	return
 }
 
-func ReportToJpeg(reportUrl, filePath string) (err error) {
+func ReportToJpeg(width int, reportUrl, filePath string) (err error) {
 	pyCode := `
 import asyncio
 from pyppeteer import launch, errors
@@ -212,7 +219,7 @@ async def main():
         
         # 设置视口大小
         await page.setViewport({
-            'width': 1920,
+            'width': %d,
             'height': 1080
         })
         
@@ -221,11 +228,15 @@ async def main():
             'waitUntil': 'networkidle0',
             'timeout': 1000000  # 设置超时时间为 100 秒
         })
-        
-        # 截取全页面的屏幕截图
+        # Customizing footer for page numbers starting from page 2
+
+        # 在这里添加两秒的等待
+        await asyncio.sleep(2)
+
         await page.screenshot({
             'path': "%s",
             'fullPage': True,
+			'quality':100
         })
         
     except errors.BrowserError as e:
@@ -250,14 +261,17 @@ finally:
     loop.close()
 `
 
-	pyCode = fmt.Sprintf(pyCode, utils.ChromePath, reportUrl, filePath)
+	pyCode = fmt.Sprintf(pyCode, utils.ChromePath, width, reportUrl, filePath)
 	utils.FileLog.Info("jpeg pyCode: \n" + pyCode)
 	cmd := exec.Command("python3", "-c", pyCode)
 
-	_, err = cmd.CombinedOutput()
-	if err != nil {
+	output, e := cmd.CombinedOutput()
+	if e != nil {
+		err = e
 		utils.FileLog.Info("ReportToJpeg failed: , error: \n" + err.Error())
+		utils.FileLog.Info("Output: %s\n", string(output))
 		go alarm_msg.SendAlarmMsg("ReportToJpeg failed:"+err.Error(), 3)
+		go alarm_msg.SendAlarmMsg("Output :"+string(output), 3)
 	}
 	defer func() {
 		cmd.Process.Kill()
@@ -265,7 +279,7 @@ finally:
 	return
 }
 
-func Report2pdfAndJpeg(reportUrl string, reportId,reportType int) {
+func Report2pdfAndJpeg(reportUrl string, reportId, reportType int) {
 	var err error
 
 	defer func() {
@@ -274,6 +288,28 @@ func Report2pdfAndJpeg(reportUrl string, reportId,reportType int) {
 			utils.FileLog.Info("Report2pdfAndJpeg failed: , error: \n" + err.Error())
 		}
 	}()
+
+	// 先清空字段
+	if reportType == 1 {
+		err = models.UpdatePdfUrlReportById(reportId)
+		if err != nil {
+			utils.FileLog.Info("清空pdf长图字段失败, Err: \n" + err.Error())
+			return
+		}
+	} else if reportType == 2 {
+		err = models.UpdatePdfUrlEnglishReportById(reportId)
+		if err != nil {
+			utils.FileLog.Info("清空pdf长图字段失败, Err: \n" + err.Error())
+			return
+		}
+	} else if reportType == 3 {
+		err = smart_report.UpdatePdfUrlSmartReportById(reportId)
+		if err != nil {
+			utils.FileLog.Info("清空pdf长图字段失败, Err: \n" + err.Error())
+			return
+		}
+	}
+
 	reportCode := utils.MD5(strconv.Itoa(reportId))
 
 	pdfPath := `./static/` + reportCode + ".pdf"
@@ -341,7 +377,11 @@ func Report2pdfAndJpeg(reportUrl string, reportId,reportType int) {
 	}()
 
 	go func() {
-		err := ReportToJpeg(reportUrl, jpegPath)
+		width := 1200
+		if reportType == 3 {
+			width = 800
+		}
+		err := ReportToJpeg(width, reportUrl, jpegPath)
 		if err != nil {
 			utils.FileLog.Info("ReportToJpeg failed: , error: \n" + err.Error())
 		}
@@ -396,4 +436,4 @@ func Report2pdfAndJpeg(reportUrl string, reportId,reportType int) {
 		}
 
 	}()
-}
+}

+ 22 - 0
utils/common.go

@@ -2260,3 +2260,25 @@ func MillisecondsToHHMMSS(ms int) string {
 func ByteToMB(byteCount int) float64 {
 	return float64(byteCount) / (1024 * 1024)
 }
+
+// DateConvMysqlConvMongo
+// @Description: 将mysql中的日期比较符转换成mongo中的日期比较符
+// @author: Roc
+// @datetime 2024-05-08 11:03:26
+// @param dateCon string
+func DateConvMysqlConvMongo(dateCon string) string {
+	cond := ""
+	switch dateCon {
+	case "=":
+		cond = "$eq"
+	case "<":
+		cond = "$lt"
+	case "<=":
+		cond = "$lte"
+	case ">":
+		cond = "$gt"
+	case ">=":
+		cond = "$gte"
+	}
+	return cond
+}

+ 14 - 3
utils/config.go

@@ -4,6 +4,7 @@ import (
 	"fmt"
 	beeLogger "github.com/beego/bee/v2/logger"
 	"github.com/beego/beego/v2/server/web"
+	"github.com/qiniu/qmgo"
 	"strconv"
 )
 
@@ -16,11 +17,14 @@ var (
 	MYSQL_URL_GL     string
 	MYSQL_LOG_URL    string
 	MYSQL_WEEKLY_URL string //用户主库
+	MgoUrlData       string // mongodb数据库连接配置
 
 	REDIS_CACHE string //缓存地址
 	//Rc          *cache.Cache //redis缓存
-	Re error       //redis错误
-	Rc RedisClient //redis缓存
+	Re            error        //redis错误
+	Rc            RedisClient  //redis缓存
+	MgoDataCli    *qmgo.Client // mongodb客户端连接
+	MgoDataDbName string       // mongodb指标数据的库名
 )
 
 // 基础配置
@@ -196,7 +200,11 @@ var (
 
 // chrome配置
 var (
-	ChromePath       string // chrome浏览器地址
+	ChromePath string // chrome浏览器地址
+)
+
+var (
+	UseMongo bool // 是否使用mongo
 )
 
 func init() {
@@ -236,6 +244,9 @@ func init() {
 	MYSQL_LOG_URL = config["mysql_url_log"]
 	MYSQL_WEEKLY_URL = config["mysql_url_weekly"]
 
+	// mongodb数据库连接配置
+	MgoUrlData = config["mgo_url_data"]
+
 	REDIS_CACHE = config["beego_cache"]
 	if len(REDIS_CACHE) <= 0 {
 		panic("redis链接参数没有配置")

+ 4 - 0
utils/constants.go

@@ -162,6 +162,7 @@ const (
 	DATA_SOURCE_CALCULATE_RJZ                                   // 日均值计算->75
 	DATA_SOURCE_GFEX                                 = 78       // 广州期货交易所->76
 	DATA_SOURCE_ICPI                                 = 79       // ICPI消费价格指数->79
+	DATA_SOURCE_BUSINESS                             = 84       // 来源于自有数据
 )
 
 // 数据刷新频率
@@ -213,6 +214,7 @@ const (
 	CACHE_EN_PPT_EDITING              = "eta:en_ppt:editing:"               // 英文PPT用户编辑中
 	CACHE_SMART_REPORT_EDITING        = "eta:smart_report:editing:"         // 智能研报用户编辑中
 	CACHE_SMART_REPORT_SEND_MSG       = "eta:smart_report:sending:"         // 智能研报用户报告推送
+	CACHE_KEY_REPLACE_EDB             = "eta:replace_edb"                   //系统用户操作日志队列
 )
 
 // 模板消息推送类型
@@ -318,6 +320,7 @@ const (
 	CHART_SOURCE_LINE_FEATURE_PERCENTILE         = 8  // 统计特征-百分位图表
 	CHART_SOURCE_LINE_FEATURE_FREQUENCY          = 9  // 统计特征-频率分布图表
 	CHART_SOURCE_CROSS_HEDGING                   = 10 // 跨品种分析图表
+	CHART_SOURCE_BALANCE_EXCEL                   = 11 // 平衡表图表
 )
 
 // 批量配置图表的位置来源
@@ -340,6 +343,7 @@ const (
 	TIME_TABLE            = 2 // 时间序列表格
 	MIXED_TABLE           = 3 // 混合表格
 	CUSTOM_ANALYSIS_TABLE = 4 // 自定义分析表格
+	BALANCE_TABLE         = 5 // 平衡表
 )
 
 // 图表样式类型

+ 37 - 0
utils/logs.go

@@ -18,6 +18,7 @@ var FileLog *logs.BeeLogger
 var ApiLog *logs.BeeLogger
 var FileLogData *logs.BeeLogger
 var Binlog *logs.BeeLogger
+var MongoLog *logs.BeeLogger
 
 func init() {
 	if LogMaxDays == 0 {
@@ -46,6 +47,7 @@ func init() {
 	initBinlog()
 	initApiLog()
 	initFileLogData()
+	initMgoLog()
 }
 
 type logConfig struct {
@@ -128,6 +130,41 @@ func initFileLogData() {
 	FileLogData.EnableFuncCallDepth(true)
 }
 
+// initMgoLog
+// @Description: mongo日志
+// @author: Roc
+// @datetime 2024-05-06 16:42:47
+func initMgoLog() {
+	//mgo日志
+
+	var logPath string
+	{
+		binlogPath := BinLogPath
+		if binlogPath == "" {
+			binlogPath = DefaultBinlogPath
+		}
+		logPath = path.Dir(binlogPath)
+	}
+	if logPath == `` {
+		logPath = "./etalogs"
+	}
+
+	mongoLogPath := logPath + "/mongolog"
+	mongoLogFile := "mongolog.log"
+
+	os.MkdirAll(mongoLogPath, os.ModePerm)
+	logFileName := path.Join(mongoLogPath, mongoLogFile)
+	MongoLog = logs.NewLogger(1000000)
+	logConf := getDefaultLogConfig()
+
+	logConf.FileName = logFileName
+	//logConf.MaxLines = 10000000
+	//logConf.Rotate = true
+	b, _ := json.Marshal(logConf)
+	MongoLog.SetLogger(logs.AdapterFile, string(b))
+	MongoLog.EnableFuncCallDepth(true)
+}
+
 func getDefaultLogConfig() logConfig {
 	return logConfig{
 		FileName: "",

+ 137 - 0
utils/mgodb/mgo_config.go

@@ -0,0 +1,137 @@
+package mgodb
+
+import (
+	"context"
+	"eta/eta_mobile/utils"
+	"github.com/qiniu/qmgo"
+	"github.com/qiniu/qmgo/options"
+	"go.mongodb.org/mongo-driver/bson"
+	"go.mongodb.org/mongo-driver/event"
+	mgoptions "go.mongodb.org/mongo-driver/mongo/options"
+	"sync"
+)
+
+var (
+	ConnectTimeoutMS = int64(3000)
+	SocketTimeoutMS  = int64(500000)
+	MaxPoolSize      = uint64(50)
+	MinPoolSize      = uint64(0)
+)
+
+//func init() {
+//	fmt.Println("start MgoNewClient")
+//	MgoNewClient()
+//	fmt.Println("end MgoNewClient")
+//}
+
+type MgoConfig struct {
+	Host          string `json:"host"`
+	Url           string `json:"url"`
+	Port          string `json:"port"`
+	Username      string `json:"username"`
+	Password      string `json:"password"`
+	AuthSource    string `json:"authSource"`
+	AuthMechanism string `json:"auth_mechanism"`
+	Database      string `json:"database"`
+}
+
+// MgoNewClient
+// @Description: 创建一个mongodb客户端链接
+// @author: Roc
+// @datetime 2024-04-25 14:01:14
+// @return *qmgo.Client
+func MgoNewClient(mgoConfig MgoConfig) *qmgo.Client {
+	// 创建cmdMonitor,用于打印SQL
+	//startedCommands := make(map[int64]bson.Raw)
+	startedCommands := sync.Map{} // map[int64]bson.Raw
+
+	cmdMonitor := &event.CommandMonitor{
+		Started: func(_ context.Context, evt *event.CommandStartedEvent) {
+			startedCommands.Store(evt.RequestID, evt.Command)
+			//startedCommands[evt.RequestID] = evt.Command
+		},
+		Succeeded: func(_ context.Context, evt *event.CommandSucceededEvent) {
+			//log.Printf("Command: %v Reply: %v\n",
+			//	startedCommands[evt.RequestID],
+			//	evt.Reply,
+			//)
+			var commands bson.Raw
+			v, ok := startedCommands.Load(evt.RequestID)
+			if ok {
+				commands = v.(bson.Raw)
+			}
+			//utils.MongoLog.Info("\n【MongoDB】[%.3fms] [%v] %v \n", float64(evt.Duration)/1e6, commands, evt.Reply)
+			utils.MongoLog.Info("\n【MongoDB】[%.3fms] [%v] \n", float64(evt.Duration)/1e6, commands)
+		},
+		Failed: func(_ context.Context, evt *event.CommandFailedEvent) {
+			//log.Printf("Command: %v Failure: %v\n",
+			//	startedCommands[evt.RequestID],
+			//	evt.Failure,
+			//)
+			var commands bson.Raw
+			v, ok := startedCommands.Load(evt.RequestID)
+			if ok {
+				commands = v.(bson.Raw)
+			}
+			utils.MongoLog.Info("\n【MongoDB】[%.3fms] [%v] \n %v \n", float64(evt.Duration)/1e6, commands, evt.Failure)
+		},
+	}
+
+	// 创建options
+	ops := options.ClientOptions{ClientOptions: &mgoptions.ClientOptions{}}
+	ops.SetMonitor(cmdMonitor)
+
+	ctx := context.Background()
+
+	//mongodb+srv://myDatabaseUser:D1fficultP%40ssw0rd@mongodb0.example.com/?authSource=admin&replicaSet=myRepl
+
+	//var mongoUrl string
+	//if mgoConfig.Password != "" {
+	//	mongoUrl = "mongodb://" + mgoConfig.Username + ":" + mgoConfig.Password + "@" +
+	//		mgoConfig.Host + ":" + mgoConfig.Port
+	//
+	//	if mgoConfig.AuthSource != `` {
+	//		mongoUrl += mongoUrl + "?&authSource=" + mgoConfig.AuthSource
+	//	}
+	//} else {
+	//	mongoUrl = "mongodb://" + mgoConfig.Host + ":" + mgoConfig.Port
+	//}
+
+	// 创建一个数据库链接
+	client, err := qmgo.NewClient(ctx, &qmgo.Config{
+		Uri: mgoConfig.Url,
+		Auth: &qmgo.Credential{
+			AuthMechanism: mgoConfig.AuthMechanism,
+			AuthSource:    mgoConfig.AuthSource,
+			Username:      mgoConfig.Username,
+			Password:      mgoConfig.Password,
+			//PasswordSet:   false,
+		},
+		Database:         mgoConfig.Database,
+		ConnectTimeoutMS: &ConnectTimeoutMS,
+		SocketTimeoutMS:  &SocketTimeoutMS,
+		MaxPoolSize:      &MaxPoolSize,
+		MinPoolSize:      &MinPoolSize,
+	}, ops)
+
+	if err != nil {
+		panic("MongoDB连接异常:" + err.Error())
+	}
+
+	return client
+}
+
+func MgoGetColl(collName string) (cli *qmgo.QmgoClient, err error) {
+	ctx := context.Background()
+	config := &qmgo.Config{
+		//Uri:              MGO_URL,
+		//Database:         MGO_DB,
+		Coll:             collName,
+		ConnectTimeoutMS: &ConnectTimeoutMS,
+		SocketTimeoutMS:  &SocketTimeoutMS,
+		MaxPoolSize:      &MaxPoolSize,
+		MinPoolSize:      &MinPoolSize,
+	}
+	cli, err = qmgo.Open(ctx, config)
+	return
+}