xyxie 7 months ago
parent
commit
bd84542269

+ 20 - 33
controllers/data_manage/range_analysis/chart_info.go

@@ -8,8 +8,8 @@ import (
 	"eta/eta_api/models/data_manage/correlation/request"
 	"eta/eta_api/models/system"
 	"eta/eta_api/services/data"
-	correlationServ "eta/eta_api/services/data/correlation"
 	"eta/eta_api/services/data/data_manage_permission"
+	rangeServ "eta/eta_api/services/data/range_analysis"
 	"eta/eta_api/utils"
 	"fmt"
 	"github.com/rdlucklib/rdluck_tools/paging"
@@ -108,41 +108,28 @@ func (this *RangeChartChartInfoController) Preview() {
 			return
 		}
 	}
-	if req.LeadValue < 0 {
-		br.Msg = "期数需大于等于0"
-		return
-	}
-	if req.StartDate == "" || req.EndDate == "" {
-		br.Msg = "请选择开始和结束日期"
-		return
-	}
 
 	// 获取指标信息
-	edbInfoMappingA, e := data_manage.GetChartEdbMappingByEdbInfoId(req.EdbInfoIdList[0].EdbInfoId)
+	edbInfoMapping, e := data_manage.GetChartEdbMappingByEdbInfoId(req.EdbInfoId)
 	if e != nil {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取区间计算图表, A指标mapping信息失败, Err:" + e.Error()
 		return
 	}
-	edbInfoMappingB, e := data_manage.GetChartEdbMappingByEdbInfoId(req.EdbInfoIdList[1].EdbInfoId)
-	if e != nil {
-		br.Msg = "获取失败"
-		br.ErrMsg = "获取区间计算图表, B指标mapping信息失败, Err:" + e.Error()
-		return
-	}
+
 	chartInfo := new(data_manage.ChartInfoView)
 	chartInfo.ChartType = 9
 
 	//chartInfo.CorrelationLeadUnit = req.LeadUnit
 	// 获取图表x轴y轴
-	xEdbIdValue, yDataList, e := correlationServ.GetChartDataByEdbInfo(edbInfoMappingA, edbInfoMappingB, req.LeadValue, req.LeadUnit, req.StartDate, req.EndDate, "")
+	xEdbIdValue, yDataList, e := rangeServ.GetChartDataByEdbInfo(edbInfoMappingA, edbInfoMappingB, req.LeadValue, req.LeadUnit, req.StartDate, req.EndDate, "")
 	if e != nil {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取区间计算图表, 图表计算值失败, Err:" + e.Error()
 		return
 	}
 	// 完善指标信息
-	edbList, e := correlationServ.GetChartEdbInfoFormat(chartInfo.ChartInfoId, edbInfoMappingA, edbInfoMappingB)
+	edbList, e := rangeServ.GetChartEdbInfoFormat(chartInfo.ChartInfoId, edbInfoMappingA, edbInfoMappingB)
 	if e != nil {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取区间计算图表, 完善指标信息失败, Err:" + e.Error()
@@ -162,7 +149,7 @@ func (this *RangeChartChartInfoController) Preview() {
 	resp.EdbInfoList = edbList
 	resp.XEdbIdValue = xEdbIdValue
 	resp.YDataList = yDataList
-	resp.CorrelationChartInfo = correlationInfo
+	resp.DataResp = correlationInfo
 	br.Data = resp
 	br.Ret = 200
 	br.Success = true
@@ -210,7 +197,7 @@ func (this *RangeChartChartInfoController) Add() {
 		return
 	}
 
-	chartInfo, err, errMsg, isSendEmail := correlationServ.AddChartInfo(req, utils.CHART_SOURCE_CORRELATION, sysUser, this.Lang)
+	chartInfo, err, errMsg, isSendEmail := rangeServ.AddChartInfo(req, utils.CHART_SOURCE_CORRELATION, sysUser, this.Lang)
 	if err != nil {
 		br.Msg = "保存失败"
 		if errMsg != `` {
@@ -277,7 +264,7 @@ func (this *RangeChartChartInfoController) Edit() {
 		return
 	}
 
-	chartItem, err, errMsg, isSendEmail := correlationServ.EditChartInfo(req, sysUser, this.Lang)
+	chartItem, err, errMsg, isSendEmail := rangeServ.EditChartInfo(req, sysUser, this.Lang)
 	if err != nil {
 		br.Msg = "保存失败"
 		if errMsg != `` {
@@ -769,7 +756,7 @@ func (this *RangeChartChartInfoController) Detail() {
 			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, chartInfo.ExtraConfig)
+			xEdbIdValue, yDataList, e = rangeServ.GetChartDataByEdbInfo(edbInfoMappingA, edbInfoMappingB, correlationChart.LeadValue, correlationChart.LeadUnit, startDate, endDate, chartInfo.ExtraConfig)
 			if e != nil {
 				br.Msg = "获取失败"
 				br.ErrMsg = "获取区间计算图表, 图表计算值失败, Err:" + e.Error()
@@ -777,7 +764,7 @@ func (this *RangeChartChartInfoController) Detail() {
 			}
 		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)
+			dataResp, e = rangeServ.GetRollingCorrelationChartDataByEdbInfo(edbInfoMappingA, edbInfoMappingB, correlationChart.LeadValue, correlationChart.LeadUnit, correlationChart.CalculateValue, correlationChart.CalculateUnit, startDate, endDate, chartInfo.ChartName, chartInfo.ChartNameEn)
 			if e != nil {
 				br.Msg = "获取失败"
 				br.ErrMsg = "获取滚动区间计算图表, 图表计算值失败, Err:" + e.Error()
@@ -785,7 +772,7 @@ func (this *RangeChartChartInfoController) Detail() {
 			}
 		}
 	} else {
-		xEdbIdValue, yDataList, e = correlationServ.GetFactorChartDataByChartId(chartInfoId, chartInfo.ExtraConfig)
+		xEdbIdValue, yDataList, e = rangeServ.GetFactorChartDataByChartId(chartInfoId, chartInfo.ExtraConfig)
 		if e != nil {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取区间计算图表, 图表计算值失败, Err:" + e.Error()
@@ -796,7 +783,7 @@ func (this *RangeChartChartInfoController) Detail() {
 	// 完善指标信息
 	edbList := make([]*data_manage.ChartEdbInfoMapping, 0)
 	if correlationChart.AnalysisMode != 1 {
-		edbList, e = correlationServ.GetChartEdbInfoFormat(chartInfo.ChartInfoId, edbInfoMappingA, edbInfoMappingB)
+		edbList, e = rangeServ.GetChartEdbInfoFormat(chartInfo.ChartInfoId, edbInfoMappingA, edbInfoMappingB)
 		if e != nil {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取区间计算图表, 完善指标信息失败, Err:" + e.Error()
@@ -1114,7 +1101,7 @@ func (this *RangeChartChartInfoController) Refresh() {
 	}
 
 	// 刷新区间计算图表
-	isAsync, e := correlationServ.ChartInfoRefresh(chartInfo.ChartInfoId, chartInfo.UniqueCode)
+	isAsync, e := rangeServ.ChartInfoRefresh(chartInfo.ChartInfoId, chartInfo.UniqueCode)
 	if e != nil {
 		br.Msg = "刷新失败"
 		br.ErrMsg = "刷新区间计算图表失败, Err:" + err.Error()
@@ -1293,7 +1280,7 @@ func (this *RangeChartChartInfoController) Copy() {
 			},
 		}
 
-		newChart, err, errMsg, isSendEmail := correlationServ.CopyChartInfo(multipleGraphConfigChartMapping.MultipleGraphConfigId, req.ChartClassifyId, req.ChartName, correlationChartInfoReq, originChart, sysUser, this.Lang)
+		newChart, err, errMsg, isSendEmail := rangeServ.CopyChartInfo(multipleGraphConfigChartMapping.MultipleGraphConfigId, req.ChartClassifyId, req.ChartName, correlationChartInfoReq, originChart, sysUser, this.Lang)
 		chartInfo = newChart
 
 		if err != nil {
@@ -1663,7 +1650,7 @@ func GetChartInfoDetailFromUniqueCode(chartInfo *data_manage.ChartInfoView, isCa
 			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, chartInfo.ExtraConfig)
+			xEdbIdValue, yDataList, e = rangeServ.GetChartDataByEdbInfo(edbInfoMappingA, edbInfoMappingB, correlationChart.LeadValue, correlationChart.LeadUnit, startDate, endDate, chartInfo.ExtraConfig)
 			if e != nil {
 				msg = "获取失败"
 				errMsg = "获取区间计算图表, 图表计算值失败, Err:" + e.Error()
@@ -1672,7 +1659,7 @@ func GetChartInfoDetailFromUniqueCode(chartInfo *data_manage.ChartInfoView, isCa
 		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)
+			dataResp, e = rangeServ.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()
@@ -1680,7 +1667,7 @@ func GetChartInfoDetailFromUniqueCode(chartInfo *data_manage.ChartInfoView, isCa
 			}
 		}
 	} else {
-		xEdbIdValue, yDataList, e = correlationServ.GetFactorChartDataByChartId(chartInfoId, chartInfo.ExtraConfig)
+		xEdbIdValue, yDataList, e = rangeServ.GetFactorChartDataByChartId(chartInfoId, chartInfo.ExtraConfig)
 		if e != nil {
 			msg = "获取失败"
 			errMsg = "获取区间计算图表, 图表计算值失败, Err:" + e.Error()
@@ -1691,7 +1678,7 @@ func GetChartInfoDetailFromUniqueCode(chartInfo *data_manage.ChartInfoView, isCa
 	// 完善指标信息
 	edbList := make([]*data_manage.ChartEdbInfoMapping, 0)
 	if correlationChart.AnalysisMode != 1 {
-		edbList, e = correlationServ.GetChartEdbInfoFormat(chartInfo.ChartInfoId, edbInfoMappingA, edbInfoMappingB)
+		edbList, e = rangeServ.GetChartEdbInfoFormat(chartInfo.ChartInfoId, edbInfoMappingA, edbInfoMappingB)
 		if e != nil {
 			msg = "获取失败"
 			errMsg = "获取区间计算图表, 完善指标信息失败, Err:" + e.Error()
@@ -1828,7 +1815,7 @@ func (this *RangeChartChartInfoController) EnInfoEdit() {
 		return
 	}
 
-	chartItem, _, tips, e := correlationServ.GetChartAndCorrelationInfo(req.ChartInfoId)
+	chartItem, _, tips, e := rangeServ.GetChartAndCorrelationInfo(req.ChartInfoId)
 	if e != nil {
 		if tips != "" {
 			br.Msg = tips
@@ -2090,7 +2077,7 @@ func (this *RangeChartChartInfoController) BaseInfoEdit() {
 		return
 	}
 
-	chartItem, _, tips, e := correlationServ.GetChartAndCorrelationInfo(req.ChartInfoId)
+	chartItem, _, tips, e := rangeServ.GetChartAndCorrelationInfo(req.ChartInfoId)
 	if e != nil {
 		if tips != "" {
 			br.Msg = tips

+ 12 - 0
models/data_manage/chart_info_range_analysis.go

@@ -1,5 +1,7 @@
 package data_manage
 
+import "go.starlark.net/lib/time"
+
 type ChartRangeAnalysisExtraConf struct {
 	EdbInfoMode          int                                `description:"指标模式 0: 单指标,1: 多指标"`
 	DateRangeType        int                                `description:"区间划分类型 0:智能划分,1:手工划分,2:跨年划分"`
@@ -70,3 +72,13 @@ func (a ChartRangeAnalysisManualDateConfList) Swap(i, j int) { a[i], a[j] = a[j]
 func (a ChartRangeAnalysisManualDateConfList) Less(i, j int) bool {
 	return a[i].StartDate < a[j].StartDate
 }
+
+type ChartRangeAnalysisDataResp struct { //图表详情返回值
+	ChartRangeAnalysisExtraConf
+}
+
+type ChartRangeAnalysisDateDataItem struct {
+	StartDate time.Time
+	EndDate   time.Time
+	DataList  []EdbDataList
+}

+ 1573 - 0
services/data/range_analysis/chart_info.go

@@ -1 +1,1574 @@
 package range_analysis
+
+import (
+	"encoding/json"
+	"errors"
+	"eta/eta_api/models/data_manage"
+	"eta/eta_api/models/system"
+	"eta/eta_api/services/alarm_msg"
+	"eta/eta_api/services/data"
+	"eta/eta_api/utils"
+	"fmt"
+	"github.com/shopspring/decimal"
+	"math"
+	"sort"
+	"strconv"
+	"strings"
+	"time"
+)
+
+// HandleDataByLinearRegression 线性方程插值法补全数据
+func HandleDataByLinearRegression(originList []*data_manage.EdbDataList, handleDataMap map[string]float64) (newList []*data_manage.EdbDataList, err error) {
+	if len(originList) < 2 {
+		return
+	}
+
+	var startEdbInfoData *data_manage.EdbDataList
+	for _, v := range originList {
+		handleDataMap[v.DataTime] = v.Value
+
+		// 第一个数据就给过滤了,给后面的试用
+		if startEdbInfoData == nil {
+			startEdbInfoData = v
+			newList = append(newList, &data_manage.EdbDataList{
+				DataTime: v.DataTime,
+				Value:    v.Value,
+			})
+			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
+			newList = append(newList, &data_manage.EdbDataList{
+				DataTime: v.DataTime,
+				Value:    v.Value,
+			})
+			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 = fmt.Errorf("线性方程公式生成失败")
+				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
+				newList = append(newList, &data_manage.EdbDataList{
+					DataTime: tmpDataTime.Format(utils.FormatDate),
+					Value:    val,
+				})
+			}
+		}
+
+		// 最后将自己赋值
+		newList = append(newList, &data_manage.EdbDataList{
+			EdbDataId: v.EdbDataId,
+			DataTime:  v.DataTime,
+			Value:     v.Value,
+		})
+
+		startEdbInfoData = v
+	}
+	return
+}
+
+// MoveDataDaysToNewDataList 平移指标数据生成新的数据序列
+func MoveDataDaysToNewDataList(dataList []*data_manage.EdbDataList, moveDay int) (newDataList []data_manage.EdbDataList, dateDataMap map[string]float64) {
+	dateMap := make(map[time.Time]float64)
+	var minDate, maxDate time.Time
+	dateDataMap = make(map[string]float64)
+
+	for _, v := range dataList {
+		currDate, _ := time.ParseInLocation(utils.FormatDate, v.DataTime, time.Local)
+		if minDate.IsZero() || currDate.Before(minDate) {
+			minDate = currDate
+		}
+		if maxDate.IsZero() || currDate.After(maxDate) {
+			maxDate = currDate
+		}
+		dateMap[currDate] = v.Value
+	}
+
+	// 处理领先、滞后数据
+	newDateMap := make(map[time.Time]float64)
+	for currDate, value := range dateMap {
+		newDate := currDate.AddDate(0, 0, moveDay)
+		newDateMap[newDate] = value
+	}
+	minDate = minDate.AddDate(0, 0, moveDay)
+	maxDate = maxDate.AddDate(0, 0, moveDay)
+
+	// 获取日期相差日
+	dayNum := utils.GetTimeSubDay(minDate, maxDate)
+
+	for i := 0; i <= dayNum; i++ {
+		currDate := minDate.AddDate(0, 0, i)
+		tmpValue, ok := newDateMap[currDate]
+		if !ok {
+			//找不到数据,那么就用前面的数据吧
+			if len(newDataList)-1 < 0 {
+				tmpValue = 0
+			} else {
+				tmpValue = newDataList[len(newDataList)-1].Value
+			}
+		}
+		tmpData := data_manage.EdbDataList{
+			DataTime: currDate.Format(utils.FormatDate),
+			Value:    tmpValue,
+		}
+		dateDataMap[tmpData.DataTime] = tmpData.Value
+		newDataList = append(newDataList, tmpData)
+	}
+	return
+}
+
+// GetChartEdbInfoFormat 相关性图表-获取指标信息
+func GetChartEdbInfoFormat(chartInfoId int, edbInfoMappingA, edbInfoMappingB *data_manage.ChartEdbInfoMapping) (edbList []*data_manage.ChartEdbInfoMapping, err error) {
+	edbList = make([]*data_manage.ChartEdbInfoMapping, 0)
+	if edbInfoMappingA == nil || edbInfoMappingB == nil {
+		err = fmt.Errorf("指标信息有误")
+		return
+	}
+
+	edbInfoMappingA.FrequencyEn = data.GetFrequencyEn(edbInfoMappingA.Frequency)
+	if edbInfoMappingA.Unit == `无` {
+		edbInfoMappingA.Unit = ``
+	}
+	if edbInfoMappingB.Unit == `无` {
+		edbInfoMappingB.Unit = ``
+	}
+	if chartInfoId <= 0 {
+		edbInfoMappingA.IsAxis = 1
+		edbInfoMappingA.LeadValue = 0
+		edbInfoMappingA.LeadUnit = ""
+		edbInfoMappingA.ChartEdbMappingId = 0
+		edbInfoMappingA.ChartInfoId = 0
+		edbInfoMappingA.IsOrder = false
+		edbInfoMappingA.EdbInfoType = 1
+		edbInfoMappingA.ChartStyle = ""
+		edbInfoMappingA.ChartColor = ""
+		edbInfoMappingA.ChartWidth = 0
+
+		edbInfoMappingB.IsAxis = 1
+		edbInfoMappingB.LeadValue = 0
+		edbInfoMappingB.LeadUnit = ""
+		edbInfoMappingB.ChartEdbMappingId = 0
+		edbInfoMappingB.ChartInfoId = 0
+		edbInfoMappingB.IsOrder = false
+		edbInfoMappingB.EdbInfoType = 1
+		edbInfoMappingB.ChartStyle = ""
+		edbInfoMappingB.ChartColor = ""
+		edbInfoMappingB.ChartWidth = 0
+	} else {
+		edbInfoMappingA.LeadUnitEn = data.GetLeadUnitEn(edbInfoMappingA.LeadUnit)
+		edbInfoMappingB.LeadUnitEn = data.GetLeadUnitEn(edbInfoMappingB.LeadUnit)
+	}
+	edbList = append(edbList, edbInfoMappingA, edbInfoMappingB)
+	return
+}
+
+// GetChartDataByEdbInfo 相关性图表-根据指标信息获取x轴和y轴
+func GetChartDataByEdbInfo(edbInfoMapping *data_manage.ChartEdbInfoMapping, req data_manage.ChartRangeAnalysisExtraConf) (xEdbIdValue []int, dataResp data_manage.ChartRangeAnalysisDataResp, err error) {
+	// 指标的开始日期和结束日期
+	startDateTime, _ := time.ParseInLocation(utils.FormatDate, startDate, time.Local)
+	startDate = startDateTime.AddDate(0, 0, 1).Format(utils.FormatDate)
+
+	// 根据时间区间类型来获取数据的计算窗口,然后再拼接成整段数据
+	// 智能划分得到一个开始日期,和结束日期
+	// 手工划分得到多个开始日期和结束日期(已排序)
+	// 跨年划分得到多个开始日期和结束日期
+
+	//// 2023-03-02 时间序列始终以指标B为基准, 始终是A进行平移
+	//baseEdbInfo := edbInfoMappingB
+	//changeEdbInfo := edbInfoMappingA
+	// 2023-03-17 时间序列始终以指标A为基准, 始终是B进行平移
+	baseEdbInfo := edbInfoMapping
+	changeEdbInfo := edbInfoMappingB
+
+	// 获取时间基准指标在时间区间内的值
+	aDataList := make([]*data_manage.EdbDataList, 0)
+	switch baseEdbInfo.EdbInfoCategoryType {
+	case 0:
+		aDataList, err = data_manage.GetEdbDataList(baseEdbInfo.Source, baseEdbInfo.SubSource, baseEdbInfo.EdbInfoId, startDate, endDate)
+	case 1:
+		_, aDataList, _, _, err, _ = data.GetPredictDataListByPredictEdbInfoId(baseEdbInfo.EdbInfoId, startDate, endDate, false)
+	default:
+		err = errors.New("指标base类型异常")
+		return
+	}
+
+	// 获取变频指标所有日期的值, 插值法完善数据
+	bDataList := make([]*data_manage.EdbDataList, 0)
+	switch changeEdbInfo.EdbInfoCategoryType {
+	case 0:
+		bDataList, err = data_manage.GetEdbDataList(changeEdbInfo.Source, changeEdbInfo.SubSource, changeEdbInfo.EdbInfoId, "", "")
+	case 1:
+		_, bDataList, _, _, err, _ = data.GetPredictDataListByPredictEdbInfoId(changeEdbInfo.EdbInfoId, "", "", false)
+	default:
+		err = errors.New("指标change类型异常")
+		return
+	}
+	//changeDataMap := make(map[string]float64)
+	//newChangeDataList, e := HandleDataByLinearRegression(bDataList, changeDataMap)
+	//if e != nil {
+	//	err = fmt.Errorf("获取变频指标插值法Map失败, Err: %s", e.Error())
+	//	return
+	//}
+
+	// 2023-03-17 时间序列始终以指标A为基准, 始终是B进行平移
+	baseDataList := make([]*data_manage.EdbDataList, 0)
+	baseDataMap := make(map[string]float64)
+	changeDataList := make([]*data_manage.EdbDataList, 0)
+	changeDataMap := make(map[string]float64)
+
+	// 先把低频指标升频为高频
+	{
+		frequencyIntMap := map[string]int{
+			"日度": 1,
+			"周度": 2,
+			"旬度": 3,
+			"月度": 4,
+			"季度": 5,
+			"年度": 6,
+		}
+
+		// 如果A指标是高频,那么就需要对B指标进行升频
+		if frequencyIntMap[edbInfoMappingA.Frequency] < frequencyIntMap[edbInfoMappingB.Frequency] {
+			tmpNewChangeDataList, e := HandleDataByLinearRegression(bDataList, changeDataMap)
+			if e != nil {
+				err = fmt.Errorf("获取变频指标插值法Map失败, Err: %s", e.Error())
+				return
+			}
+			changeDataList = tmpNewChangeDataList
+			baseDataList = aDataList
+			for _, v := range baseDataList {
+				baseDataMap[v.DataTime] = v.Value
+			}
+
+		} else if frequencyIntMap[edbInfoMappingA.Frequency] > frequencyIntMap[edbInfoMappingB.Frequency] {
+			// 如果B指标是高频,那么就需要对A指标进行升频
+			tmpNewChangeDataList, e := HandleDataByLinearRegression(aDataList, baseDataMap)
+			if e != nil {
+				err = fmt.Errorf("获取变频指标插值法Map失败, Err: %s", e.Error())
+				return
+			}
+			baseDataList = tmpNewChangeDataList
+
+			changeDataList = bDataList
+			for _, v := range changeDataList {
+				changeDataMap[v.DataTime] = v.Value
+			}
+		} else {
+			baseDataList = aDataList
+			for _, v := range baseDataList {
+				baseDataMap[v.DataTime] = v.Value
+			}
+			changeDataList = bDataList
+			for _, v := range changeDataList {
+				changeDataMap[v.DataTime] = v.Value
+			}
+		}
+
+	}
+
+	// 计算不领先也不滞后时的相关系数
+	baseCalculateData := make([]float64, 0)
+	baseDataTimeArr := make([]string, 0)
+	for i := range baseDataList {
+		baseDataTimeArr = append(baseDataTimeArr, baseDataList[i].DataTime)
+		baseCalculateData = append(baseCalculateData, baseDataList[i].Value)
+	}
+
+	//zeroBaseData := make([]float64, 0)
+	//zeroCalculateData := make([]float64, 0)
+	//for i := range baseDataTimeArr {
+	//	tmpBaseVal, ok1 := baseDataMap[baseDataTimeArr[i]]
+	//	tmpCalculateVal, ok2 := changeDataMap[baseDataTimeArr[i]]
+	//	if ok1 && ok2 {
+	//		zeroBaseData = append(zeroBaseData, tmpBaseVal)
+	//		zeroCalculateData = append(zeroCalculateData, tmpCalculateVal)
+	//	}
+	//}
+	//if len(zeroBaseData) != len(zeroCalculateData) {
+	//	err = fmt.Errorf("相关系数两组序列元素数不一致, %d-%d", len(baseCalculateData), len(zeroCalculateData))
+	//	return
+	//}
+	//zeroRatio := utils.CalculateCorrelationByIntArr(zeroBaseData, zeroCalculateData)
+	//if leadValue == 0 {
+	//	yData = append(yData, zeroRatio)
+	//}
+
+	// 计算领先/滞后N期
+	if leadValue > 0 {
+		// 平移变频指标领先/滞后的日期(单位天)
+		moveUnitDays := utils.FrequencyDaysMap[leadUnit]
+
+		for i := range xData {
+			//if xData[i] == 0 {
+			//	yData = append(yData, zeroRatio)
+			//	continue
+			//}
+			xCalculateData := make([]float64, 0)
+			yCalculateData := make([]float64, 0)
+
+			// 平移指定天数
+			mDays := int(moveUnitDays) * xData[i]
+			_, dMap := MoveDataDaysToNewDataList(changeDataList, mDays)
+
+			// 取出对应的基准日期的值
+			for i2 := range baseDataTimeArr {
+				tmpDate := baseDataTimeArr[i2]
+				if yVal, ok := dMap[tmpDate]; ok {
+					xCalculateData = append(xCalculateData, baseCalculateData[i2])
+					yCalculateData = append(yCalculateData, yVal)
+				}
+			}
+			if len(yCalculateData) <= 0 {
+				//err = fmt.Errorf("领先滞后相关系数两组序列元素数不一致, %d-%d", len(baseCalculateData), len(yCalculateData))
+				//return
+				// 领先滞后后,没有可以计算的数据了
+				continue
+			}
+
+			// 公式计算出领先/滞后频度对应点的相关性系数
+			ratio := utils.CalculateCorrelationByIntArr(xCalculateData, yCalculateData)
+			yData = append(yData, ratio)
+		}
+	}
+
+	// 图例
+	var extra data_manage.CorrelationChartInfoExtraConfig
+	legend := new(data_manage.CorrelationChartLegend)
+	if extraConfig != "" {
+		if e := json.Unmarshal([]byte(extraConfig), &extra); e != nil {
+			err = fmt.Errorf("图例解析异常, err: %v", e)
+			return
+		}
+		if len(extra.LegendConfig) > 0 {
+			legend = extra.LegendConfig[0]
+		}
+	}
+
+	xEdbIdValue = xData
+	yDataList = make([]data_manage.YData, 0)
+	yDate := "0000-00-00"
+	var y data_manage.YData
+	y.Date = yDate
+	y.Value = yData
+	if legend != nil {
+		y.Name = legend.LegendName
+		y.Color = legend.Color
+	}
+	yDataList = append(yDataList, y)
+	return
+}
+
+// RollingCorrelationChartDataResp 滚动相关性图表数据
+type RollingCorrelationChartDataResp struct {
+	MaxData             float64
+	MinData             float64
+	LatestDate          string `description:"真实数据的最后日期"`
+	EdbInfoCategoryType int
+	ChartColor          string
+	ChartStyle          string
+	PredictChartColor   string
+	ChartType           int
+	ChartWidth          int
+	EdbName             string
+	EdbNameEn           string
+	Unit                string
+	UnitEn              string
+	IsAxis              int
+	DataList            []data_manage.EdbDataList
+}
+
+// GetRollingCorrelationChartDataByEdbInfo 滚动相关性计算
+func GetRollingCorrelationChartDataByEdbInfo(edbInfoMappingA, edbInfoMappingB *data_manage.ChartEdbInfoMapping, leadValue int, leadUnit string, calculateValue int, calculateUnit string, startDate, endDate, chartName, chartNameEn string) (dataResp RollingCorrelationChartDataResp, err error) {
+	dataResp = RollingCorrelationChartDataResp{
+		DataList:          make([]data_manage.EdbDataList, 0),
+		MaxData:           0,
+		MinData:           0,
+		ChartColor:        "#00f",
+		ChartStyle:        `spline`,
+		PredictChartColor: `#00f`,
+		ChartType:         0,
+		ChartWidth:        3,
+		EdbName:           chartName,
+		EdbNameEn:         chartNameEn,
+		IsAxis:            1,
+	}
+	dataList := make([]data_manage.EdbDataList, 0)
+
+	// 计算窗口,不包含第一天
+	startDateTime, _ := time.ParseInLocation(utils.FormatDate, startDate, time.Local)
+	startDate = startDateTime.AddDate(0, 0, 1).Format(utils.FormatDate)
+
+	baseEdbInfo := edbInfoMappingA
+	changeEdbInfo := edbInfoMappingB
+
+	// 获取时间基准指标在时间区间内的值
+	aDataList := make([]*data_manage.EdbDataList, 0)
+	switch baseEdbInfo.EdbInfoCategoryType {
+	case 0:
+		aDataList, err = data_manage.GetEdbDataList(baseEdbInfo.Source, baseEdbInfo.SubSource, baseEdbInfo.EdbInfoId, startDate, endDate)
+	case 1:
+		_, aDataList, _, _, err, _ = data.GetPredictDataListByPredictEdbInfoId(baseEdbInfo.EdbInfoId, startDate, endDate, true)
+	default:
+		err = errors.New("指标base类型异常")
+		return
+	}
+
+	// 获取变频指标所有日期的值, 插值法完善数据
+	bDataList := make([]*data_manage.EdbDataList, 0)
+	switch changeEdbInfo.EdbInfoCategoryType {
+	case 0:
+		bDataList, err = data_manage.GetEdbDataList(changeEdbInfo.Source, changeEdbInfo.SubSource, changeEdbInfo.EdbInfoId, "", "")
+	case 1:
+		_, bDataList, _, _, err, _ = data.GetPredictDataListByPredictEdbInfoId(changeEdbInfo.EdbInfoId, "", "", false)
+	default:
+		err = errors.New("指标change类型异常")
+		return
+	}
+
+	// 数据平移变频指标领先/滞后的日期(单位天)
+	// 2023-03-17 时间序列始终以指标A为基准, 始终是B进行平移
+	//baseDataList := make([]*data_manage.EdbDataList, 0)
+	baseDataMap := make(map[string]float64)
+	changeDataList := make([]*data_manage.EdbDataList, 0)
+	changeDataMap := make(map[string]float64)
+
+	// A指标不管三七二十一,先变个频再说
+	{
+		_, e := HandleDataByLinearRegression(aDataList, baseDataMap)
+		if e != nil {
+			err = fmt.Errorf("获取变频指标插值法Map失败, Err: %s", e.Error())
+			return
+		}
+		//baseDataList = tmpNewChangeDataList
+	}
+	// B指标不管三七二十一,先变个频再说
+	{
+		tmpNewChangeDataList, e := HandleDataByLinearRegression(bDataList, changeDataMap)
+		if e != nil {
+			err = fmt.Errorf("获取变频指标插值法Map失败, Err: %s", e.Error())
+			return
+		}
+		changeDataList = tmpNewChangeDataList
+
+		// 平移下日期
+		moveUnitDays := utils.FrequencyDaysMap[leadUnit]
+		_, changeDataMap = MoveDataDaysToNewDataList(changeDataList, leadValue*moveUnitDays)
+	}
+
+	// 计算计算时,需要多少个日期内数据
+	calculateDay := utils.FrequencyDaysMap[calculateUnit] * calculateValue
+
+	// 计算 每个日期的相关性值
+	{
+		startDateTime, _ := time.ParseInLocation(utils.FormatDate, startDate, time.Local)
+		if endDate == `` {
+			endDate = baseEdbInfo.EndDate
+		}
+		endDateTime, _ := time.ParseInLocation(utils.FormatDate, endDate, time.Local)
+		endDateTime = endDateTime.AddDate(0, 0, -(calculateDay - 1))
+
+		// 是否开始第一条数据
+		var isStart, isNotFirst bool
+		for currDay := startDateTime; !currDay.After(endDateTime); currDay = currDay.AddDate(0, 0, 1) {
+			yCalculateData := make([]float64, 0)
+			baseCalculateData := make([]float64, 0)
+
+			// 取出对应的基准日期的值
+			for i := 0; i < calculateDay; i++ {
+				iDay := currDay.AddDate(0, 0, i).Format(utils.FormatDate)
+
+				tmpBaseValue, ok1 := baseDataMap[iDay]
+				tmpChangeValue, ok2 := changeDataMap[iDay]
+				if ok1 && ok2 {
+					baseCalculateData = append(baseCalculateData, tmpBaseValue)
+					yCalculateData = append(yCalculateData, tmpChangeValue)
+				} else {
+					continue
+				}
+			}
+
+			// 公式计算出领先/滞后频度对应点的相关性系数
+			var ratio float64
+			if len(baseCalculateData) > 0 {
+				ratio = utils.CalculateCorrelationByIntArr(baseCalculateData, yCalculateData)
+			} else {
+				// 没有数据的话,那就不返回
+				continue
+			}
+
+			// 过滤前面都是0的数据
+			{
+				if ratio != 0 {
+					isStart = true
+				}
+
+				if !isStart {
+					continue
+				}
+			}
+
+			dataTime := currDay.AddDate(0, 0, calculateDay-1)
+			dataList = append(dataList, data_manage.EdbDataList{
+				//EdbDataId:     0,
+				EdbInfoId:     0,
+				DataTime:      dataTime.Format(utils.FormatDate),
+				DataTimestamp: dataTime.UnixNano() / 1e6,
+				Value:         ratio,
+			})
+
+			if !isNotFirst {
+				dataResp.MinData = ratio
+				dataResp.MaxData = ratio
+				isNotFirst = true
+			}
+			if dataResp.MinData > ratio {
+				dataResp.MinData = ratio
+			}
+			if dataResp.MaxData < ratio {
+				dataResp.MaxData = ratio
+			}
+		}
+		dataResp.DataList = dataList
+	}
+
+	return
+}
+
+// ChartInfoRefresh 图表刷新
+func ChartInfoRefresh(chartInfoId int, uniqueCode string) (isAsync bool, err error) {
+	var errMsg string
+	defer func() {
+		if err != nil {
+			tips := fmt.Sprintf("CorrelationChartInfoRefresh: %s", errMsg)
+			utils.FileLog.Info(tips)
+			go alarm_msg.SendAlarmMsg(tips, 3)
+		}
+	}()
+	correlationChart := new(data_manage.ChartInfoCorrelation)
+	if err = correlationChart.GetItemById(chartInfoId); err != nil {
+		errMsg = "获取相关性图表失败, Err: " + 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 {
+		return
+	}
+
+	// 重新生成数据并更新
+	edbInfoMappingA, err := data_manage.GetChartEdbMappingByEdbInfoId(correlationChart.EdbInfoIdFirst)
+	if err != nil {
+		errMsg = "获取相关性图表, A指标mapping信息失败, Err:" + err.Error()
+		return
+	}
+	edbInfoMappingB, err := data_manage.GetChartEdbMappingByEdbInfoId(correlationChart.EdbInfoIdSecond)
+	if err != nil {
+		errMsg = "获取相关性图表, B指标mapping信息失败, Err:" + err.Error()
+		return
+	}
+	periodData, correlationData, err := GetChartDataByEdbInfo(edbInfoMappingA, edbInfoMappingB, correlationChart.LeadValue, correlationChart.LeadUnit, correlationChart.StartDate.Format(utils.FormatDate), correlationChart.EndDate.Format(utils.FormatDate), "")
+	if err != nil {
+		errMsg = "获取相关性图表, 图表计算值失败, Err:" + err.Error()
+		return
+	}
+	periodDataByte, err := json.Marshal(periodData)
+	if err != nil {
+		errMsg = "相关性图表, X轴信息有误, Err:" + err.Error()
+		return
+	}
+	correlationDataByte, err := json.Marshal(correlationData[0].Value)
+	if err != nil {
+		errMsg = "相关性图表, Y轴信息有误, Err:" + err.Error()
+		return
+	}
+	correlationChart.PeriodData = string(periodDataByte)
+	correlationChart.CorrelationData = string(correlationDataByte)
+	correlationChart.ModifyTime = time.Now().Local()
+	correlationUpdateCols := []string{"PeriodData", "CorrelationData", "ModifyTime"}
+	if err = correlationChart.Update(correlationUpdateCols); err != nil {
+		errMsg = "更新相关性图表失败, Err:" + err.Error()
+		return
+	}
+	return
+}
+
+// GetChartAndCorrelationInfo 获取图表信息和相关信息信息
+func GetChartAndCorrelationInfo(chartInfoId int) (chartInfo *data_manage.ChartInfo, correlationInfo *data_manage.ChartInfoCorrelation, tips string, err error) {
+	item, e := data_manage.GetChartInfoById(chartInfoId)
+	if e != nil {
+		if e.Error() == utils.ErrNoRow() {
+			tips = "图表已被删除, 请刷新页面"
+			err = fmt.Errorf("图表已被删除, 请刷新页面")
+			return
+		}
+		err = fmt.Errorf("获取图表信息失败, Err: %s", e.Error())
+		return
+	}
+	if item.Source != utils.CHART_SOURCE_CORRELATION {
+		tips = "该图不是相关性图表"
+		err = fmt.Errorf("该图不是相关性图表")
+		return
+	}
+	chartInfo = item
+	correlationInfo = new(data_manage.ChartInfoCorrelation)
+	if e = correlationInfo.GetItemById(chartInfo.ChartInfoId); e != nil {
+		err = fmt.Errorf("获取图表相关性信息失败, Err: %s", e.Error())
+		return
+	}
+	return
+}
+
+// AddChartInfo 添加图表
+func AddChartInfo(req data_manage.AddChartInfoReq, source int, sysUser *system.Admin, lang string) (chartInfo *data_manage.ChartInfo, err error, errMsg string, isSendEmail bool) {
+	isSendEmail = true
+
+	req.ChartName = strings.Trim(req.ChartName, " ")
+	if req.ChartName == "" {
+		errMsg = "请填写图表名称!"
+		err = errors.New(errMsg)
+		isSendEmail = false
+		return
+	}
+	if req.ChartClassifyId <= 0 {
+		errMsg = "分类参数错误!"
+		err = errors.New(errMsg)
+		isSendEmail = false
+		return
+	}
+	// 相关性图表配置
+	if req.CorrelationChartInfo.LeadValue == 0 && source == utils.CHART_SOURCE_CORRELATION {
+		errMsg = "请输入领先期数"
+		err = errors.New(errMsg)
+		isSendEmail = false
+		return
+	}
+	if req.CorrelationChartInfo.LeadUnit == "" {
+		errMsg = "请填写领先单位"
+		err = errors.New(errMsg)
+		isSendEmail = false
+		return
+	}
+	//if req.CorrelationChartInfo.StartDate == "" || req.CorrelationChartInfo.EndDate == "" {
+	//	errMsg = "请填写开始结束日期"
+	//	err = errors.New(errMsg)
+	//	isSendEmail = false
+	//	return
+	//}
+	//startDate, e := time.Parse(utils.FormatDate, req.CorrelationChartInfo.StartDate)
+	//if e != nil {
+	//	errMsg = "开始日期格式有误"
+	//	err = errors.New(errMsg)
+	//	isSendEmail = false
+	//	return
+	//}
+	//endDate, e := time.Parse(utils.FormatDate, req.CorrelationChartInfo.EndDate)
+	//if e != nil {
+	//	errMsg = "结束日期格式有误"
+	//	err = errors.New(errMsg)
+	//	isSendEmail = false
+	//	return
+	//}
+	if len(req.CorrelationChartInfo.EdbInfoIdList) != 2 {
+		errMsg = "请选择AB指标"
+		err = errors.New(errMsg)
+		isSendEmail = false
+		return
+	}
+
+	chartClassify, err := data_manage.GetChartClassifyById(req.ChartClassifyId)
+	if err != nil {
+		if err.Error() == utils.ErrNoRow() {
+			errMsg = "分类不存在"
+			err = errors.New(errMsg)
+			isSendEmail = false
+			return
+		}
+		errMsg = "获取分类信息失败"
+		err = errors.New("获取分类信息失败,Err:" + err.Error())
+		return
+	}
+	if chartClassify == nil {
+		errMsg = "分类不存在"
+		err = errors.New(errMsg)
+		isSendEmail = false
+		return
+	}
+
+	var edbInfoIdArr []int
+	for _, v := range req.CorrelationChartInfo.EdbInfoIdList {
+		edbInfoId := v.EdbInfoId
+		edbInfo, tmpErr := data_manage.GetEdbInfoById(edbInfoId)
+		if tmpErr != nil {
+			if tmpErr.Error() == utils.ErrNoRow() {
+				errMsg = "指标不存在!"
+				err = errors.New("指标不存在,edbInfoId:" + strconv.Itoa(edbInfoId))
+				return
+			} else {
+				errMsg = "获取指标信息失败!"
+				err = errors.New("获取图表的指标信息失败,Err:" + tmpErr.Error())
+				return
+			}
+		}
+
+		if edbInfo == nil {
+			errMsg = "指标已被删除,请重新选择!"
+			err = errors.New("指标不存在,ChartInfoId:" + strconv.Itoa(edbInfoId))
+			return
+		} else {
+			if edbInfo.EdbInfoId <= 0 {
+				errMsg = "指标已被删除,请重新选择!"
+				err = errors.New("指标不存在,ChartInfoId:" + strconv.Itoa(edbInfoId))
+				return
+			}
+		}
+
+		edbInfoIdArr = append(edbInfoIdArr, edbInfoId)
+		edbInfo.EdbNameSource = edbInfo.EdbName
+	}
+
+	sort.Ints(edbInfoIdArr)
+	var edbInfoIdArrStr []string
+	for _, v := range edbInfoIdArr {
+		edbInfoIdArrStr = append(edbInfoIdArrStr, strconv.Itoa(v))
+	}
+	edbInfoIdStr := strings.Join(edbInfoIdArrStr, ",")
+	var chartInfoId int
+
+	// 判断图表是否存在
+	{
+		var condition string
+		var pars []interface{}
+
+		switch lang {
+		case utils.EnLangVersion:
+			condition += " AND chart_name_en = ? AND source = ? "
+		default:
+			condition += " AND chart_name=? AND source = ? "
+		}
+		pars = append(pars, req.ChartName, source)
+		count, tmpErr := data_manage.GetChartInfoCountByCondition(condition, pars)
+		if tmpErr != nil {
+			errMsg = "判断图表名称是否存在失败"
+			err = errors.New("判断图表名称是否存在失败,Err:" + tmpErr.Error())
+			return
+		}
+
+		if count > 0 {
+			errMsg = "图表已存在,请重新填写"
+			err = errors.New(errMsg)
+			isSendEmail = false
+			return
+		}
+	}
+
+	disableVal := data.CheckIsDisableChart(edbInfoIdArr)
+
+	chartInfo = new(data_manage.ChartInfo)
+	chartInfo.ChartName = req.ChartName
+	chartInfo.ChartNameEn = req.ChartName
+	chartInfo.EdbInfoIds = edbInfoIdStr
+	chartInfo.ChartClassifyId = req.ChartClassifyId
+	chartInfo.SysUserId = sysUser.AdminId
+	chartInfo.SysUserRealName = sysUser.RealName
+	chartInfo.CreateTime = time.Now()
+	chartInfo.ModifyTime = time.Now()
+	chartInfo.IsSetName = 0
+	timestamp := strconv.FormatInt(time.Now().UnixNano(), 10)
+	chartInfo.UniqueCode = utils.MD5(utils.CHART_PREFIX + "_" + timestamp)
+	chartInfo.ChartType = 9 // 相关性图
+	chartInfo.Calendar = "公历"
+	chartInfo.DateType = 6
+	chartInfo.StartDate = req.StartDate
+	chartInfo.EndDate = req.EndDate
+	chartInfo.SeasonStartDate = req.StartDate
+	chartInfo.SeasonEndDate = req.EndDate
+	chartInfo.LeftMin = req.LeftMin
+	chartInfo.LeftMax = req.LeftMax
+	chartInfo.RightMin = req.RightMin
+	chartInfo.RightMax = req.RightMax
+	chartInfo.Disabled = disableVal
+	chartInfo.Source = source
+	chartInfo.ChartThemeId = req.ChartThemeId
+	chartInfo.SourcesFrom = req.SourcesFrom
+	chartInfo.Instructions = req.Instructions
+	chartInfo.MarkersLines = req.MarkersLines
+	chartInfo.MarkersAreas = req.MarkersAreas
+	if req.ExtraConfig != "" {
+		chartInfo.ExtraConfig = req.ExtraConfig
+	}
+
+	// 指标信息
+	mapList := make([]*data_manage.ChartEdbMapping, 0)
+	for _, v := range req.CorrelationChartInfo.EdbInfoIdList {
+		mapItem := new(data_manage.ChartEdbMapping)
+		mapItem.EdbInfoId = v.EdbInfoId
+		mapItem.CreateTime = time.Now()
+		mapItem.ModifyTime = time.Now()
+		edbTimestamp := strconv.FormatInt(time.Now().UnixNano(), 10)
+		mapItem.UniqueCode = utils.MD5(utils.CHART_PREFIX + "_" + edbTimestamp + "_" + strconv.Itoa(v.EdbInfoId))
+		mapItem.IsOrder = true
+		mapItem.IsAxis = 1
+		mapItem.EdbInfoType = 1
+		mapItem.Source = utils.CHART_SOURCE_CORRELATION
+		mapList = append(mapList, mapItem)
+	}
+
+	// 相关性图表扩展信息
+	correlationChart := new(data_manage.ChartInfoCorrelation)
+	correlationChart.LeadValue = req.CorrelationChartInfo.LeadValue
+	correlationChart.LeadUnit = req.CorrelationChartInfo.LeadUnit
+	correlationChart.CalculateValue = req.CorrelationChartInfo.CalculateValue
+	correlationChart.CalculateUnit = req.CorrelationChartInfo.CalculateUnit
+	correlationChart.BaseCalculateValue = req.CorrelationChartInfo.BaseCalculateValue
+	correlationChart.BaseCalculateUnit = req.CorrelationChartInfo.BaseCalculateUnit
+
+	// 滚动相关性会有日期等信息
+	if source == utils.CHART_SOURCE_ROLLING_CORRELATION {
+		correlationChart.DateType = req.CorrelationChartInfo.DateType
+		if req.CorrelationChartInfo.StartDate != `` {
+			startDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, req.CorrelationChartInfo.StartDate, time.Local)
+			if tmpErr != nil {
+				err = tmpErr
+				return
+			}
+			correlationChart.StartDate = startDateTime
+		}
+		if req.CorrelationChartInfo.EndDate != `` {
+			endDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, req.CorrelationChartInfo.EndDate, time.Local)
+			if tmpErr != nil {
+				err = tmpErr
+				return
+			}
+			correlationChart.EndDate = endDateTime
+		}
+	}
+	correlationChart.EdbInfoIdFirst = req.CorrelationChartInfo.EdbInfoIdList[0].EdbInfoId
+	correlationChart.EdbInfoIdSecond = req.CorrelationChartInfo.EdbInfoIdList[1].EdbInfoId
+	correlationChart.CreateTime = time.Now().Local()
+	correlationChart.ModifyTime = time.Now().Local()
+	//// 生成图表x轴y轴数据
+	//edbInfoMappingA, e := data_manage.GetChartEdbMappingByEdbInfoId(req.CorrelationChartInfo.EdbInfoIdList[0].EdbInfoId)
+	//if e != nil {
+	//	errMsg = "获取失败"
+	//	err = errors.New("获取相关性图表, A指标mapping信息失败, Err:" + e.Error())
+	//	return
+	//}
+	//edbInfoMappingB, e := data_manage.GetChartEdbMappingByEdbInfoId(req.CorrelationChartInfo.EdbInfoIdList[1].EdbInfoId)
+	//if e != nil {
+	//	errMsg = "获取失败"
+	//	err = errors.New("获取相关性图表, B指标mapping信息失败, Err:" + e.Error())
+	//	return
+	//}
+	//periodData, correlationData, e := GetChartDataByEdbInfo(edbInfoMappingA, edbInfoMappingB, req.CorrelationChartInfo.LeadValue, req.CorrelationChartInfo.LeadUnit, req.CorrelationChartInfo.StartDate, req.CorrelationChartInfo.EndDate)
+	//if e != nil {
+	//	errMsg = "获取失败"
+	//	err = errors.New("获取相关性图表, 图表计算值失败, Err:" + e.Error())
+	//	return
+	//}
+	//periodDataByte, e := json.Marshal(periodData)
+	//if e != nil {
+	//	errMsg = "获取失败"
+	//	err = errors.New("相关性图表, X轴信息有误, Err:" + e.Error())
+	//	return
+	//}
+	//correlationDataByte, e := json.Marshal(correlationData[0].Value)
+	//if e != nil {
+	//	errMsg = "获取失败"
+	//	err = errors.New("相关性图表, Y轴信息有误, Err:" + e.Error())
+	//	return
+	//}
+	//correlationChart.PeriodData = string(periodDataByte)
+	//correlationChart.CorrelationData = string(correlationDataByte)
+
+	// 新增图表和指标mapping
+	chartInfoId, e := data_manage.CreateCorrelationChartAndEdb(chartInfo, mapList, correlationChart)
+	if e != nil {
+		errMsg = "操作失败"
+		err = errors.New("新增相关性图表失败, Err: " + e.Error())
+		return
+	}
+
+	// 添加指标引用记录
+	_ = data.SaveChartEdbInfoRelation(edbInfoIdArr, chartInfo)
+	//添加es数据
+	go data.EsAddOrEditChartInfo(chartInfoId)
+
+	return
+}
+
+// EditChartInfo 编辑图表
+func EditChartInfo(req data_manage.EditChartInfoReq, sysUser *system.Admin, lang string) (chartItem *data_manage.ChartInfo, err error, errMsg string, isSendEmail bool) {
+	isSendEmail = true
+
+	chartItem, err = data_manage.GetChartInfoById(req.ChartInfoId)
+	if err != nil {
+		if err.Error() == utils.ErrNoRow() {
+			errMsg = "图表已被删除,请刷新页面"
+			err = errors.New(errMsg)
+			isSendEmail = false
+			return
+		}
+		errMsg = "获取图表信息失败"
+		err = errors.New("获取图表信息失败,Err:" + err.Error())
+		return
+	}
+
+	if chartItem.Source != utils.CHART_SOURCE_CORRELATION && chartItem.Source != utils.CHART_SOURCE_ROLLING_CORRELATION {
+		errMsg = "该图不是相关性图表!"
+		err = errors.New(errMsg)
+		isSendEmail = false
+		return
+	}
+
+	req.ChartName = strings.Trim(req.ChartName, " ")
+	if req.ChartClassifyId <= 0 {
+		errMsg = "分类参数错误!"
+		err = errors.New(errMsg)
+		isSendEmail = false
+		return
+	}
+	// 相关性图表配置
+	if req.CorrelationChartInfo.LeadValue == 0 && chartItem.Source == utils.CHART_SOURCE_CORRELATION {
+		errMsg = "请输入领先期数"
+		err = errors.New(errMsg)
+		isSendEmail = false
+		return
+	}
+	if req.CorrelationChartInfo.LeadUnit == "" {
+		errMsg = "请填写领先单位"
+		err = errors.New(errMsg)
+		isSendEmail = false
+		return
+	}
+	//if req.CorrelationChartInfo.StartDate == "" || req.CorrelationChartInfo.EndDate == "" {
+	//	errMsg = "请填写开始结束日期"
+	//	err = errors.New(errMsg)
+	//	isSendEmail = false
+	//	return
+	//}
+	startDate, e := time.Parse(utils.FormatDate, req.CorrelationChartInfo.StartDate)
+	if e != nil {
+		errMsg = "开始日期格式有误"
+		err = errors.New(errMsg)
+		isSendEmail = false
+		return
+	}
+	var endDate time.Time
+	if req.CorrelationChartInfo.EndDate != `` {
+		endDate, e = time.Parse(utils.FormatDate, req.CorrelationChartInfo.EndDate)
+		if e != nil {
+			errMsg = "结束日期格式有误"
+			err = errors.New(errMsg)
+			isSendEmail = false
+			return
+		}
+	}
+	if len(req.CorrelationChartInfo.EdbInfoIdList) != 2 {
+		errMsg = "请选择AB指标"
+		err = errors.New(errMsg)
+		isSendEmail = false
+		return
+	}
+
+	chartClassify, err := data_manage.GetChartClassifyById(req.ChartClassifyId)
+	if err != nil {
+		if err.Error() == utils.ErrNoRow() {
+			errMsg = "分类不存在"
+			err = errors.New(errMsg)
+			isSendEmail = false
+			return
+		}
+		errMsg = "获取分类信息失败"
+		err = errors.New("获取分类信息失败,Err:" + err.Error())
+		return
+	}
+	if chartClassify == nil {
+		errMsg = "分类不存在"
+		err = errors.New(errMsg)
+		isSendEmail = false
+		return
+	}
+
+	// 图表操作权限
+	ok := data.CheckOpChartPermission(sysUser, chartItem.SysUserId, true)
+	if !ok {
+		errMsg = "没有该图表的操作权限"
+		err = errors.New(errMsg)
+		isSendEmail = false
+		return
+	}
+
+	var edbInfoIdArr []int
+	for _, v := range req.CorrelationChartInfo.EdbInfoIdList {
+		edbInfoId := v.EdbInfoId
+		edbInfo, tmpErr := data_manage.GetEdbInfoById(edbInfoId)
+		if tmpErr != nil {
+			if tmpErr.Error() == utils.ErrNoRow() {
+				errMsg = "图表不存在!"
+				err = errors.New("图表指标不存在,ChartInfoId:" + strconv.Itoa(edbInfoId))
+				return
+			} else {
+				errMsg = "获取图表信息失败!"
+				err = errors.New("获取图表的指标信息失败,Err:" + tmpErr.Error())
+				return
+			}
+		}
+
+		if edbInfo == nil {
+			errMsg = "指标不存在!"
+			err = errors.New("指标不存在,ChartInfoId:" + strconv.Itoa(edbInfoId))
+			return
+		}
+		edbInfoIdArr = append(edbInfoIdArr, edbInfoId)
+	}
+
+	sort.Ints(edbInfoIdArr)
+	var edbInfoIdArrStr []string
+	for _, v := range edbInfoIdArr {
+		edbInfoIdArrStr = append(edbInfoIdArrStr, strconv.Itoa(v))
+	}
+	edbInfoIdStr := strings.Join(edbInfoIdArrStr, ",")
+
+	//判断图表是否存在
+	{
+		var condition string
+		var pars []interface{}
+		condition += " AND chart_info_id <> ? "
+		pars = append(pars, req.ChartInfoId)
+		switch lang {
+		case utils.EnLangVersion:
+			condition += " AND chart_name_en = ? AND source = ? "
+		default:
+			condition += " AND chart_name=? AND source = ? "
+		}
+		pars = append(pars, req.ChartName, chartItem.Source)
+		count, tmpErr := data_manage.GetChartInfoCountByCondition(condition, pars)
+		if tmpErr != nil {
+			errMsg = "判断图表名称是否存在失败"
+			err = errors.New("判断图表名称是否存在失败,Err:" + tmpErr.Error())
+			return
+		}
+		if count > 0 {
+			errMsg = "图表已存在,请重新填写"
+			err = errors.New(errMsg)
+			isSendEmail = false
+			return
+		}
+	}
+
+	correlationChart := new(data_manage.ChartInfoCorrelation)
+	if e := correlationChart.GetItemById(chartItem.ChartInfoId); e != nil {
+		errMsg = "操作失败"
+		err = errors.New("图表相关性信息不存在, Err: " + e.Error())
+		return
+	}
+
+	// 图表启用与否
+	disableVal := data.CheckIsDisableChart(edbInfoIdArr)
+
+	// 重新生成图表值, 并修改相关性图表扩展信息
+	//edbInfoMappingA, e := data_manage.GetChartEdbMappingByEdbInfoId(req.CorrelationChartInfo.EdbInfoIdList[0].EdbInfoId)
+	//if e != nil {
+	//	errMsg = "获取失败"
+	//	err = errors.New("获取相关性图表, A指标mapping信息失败, Err:" + e.Error())
+	//	return
+	//}
+	//edbInfoMappingB, e := data_manage.GetChartEdbMappingByEdbInfoId(req.CorrelationChartInfo.EdbInfoIdList[1].EdbInfoId)
+	//if e != nil {
+	//	errMsg = "获取失败"
+	//	err = errors.New("获取相关性图表, B指标mapping信息失败, Err:" + e.Error())
+	//	return
+	//}
+	//periodData, correlationData, e := GetChartDataByEdbInfo(edbInfoMappingA, edbInfoMappingB, req.CorrelationChartInfo.LeadValue, req.CorrelationChartInfo.LeadUnit, req.CorrelationChartInfo.StartDate, req.CorrelationChartInfo.EndDate)
+	//if e != nil {
+	//	errMsg = "获取失败"
+	//	err = errors.New("获取相关性图表, 图表计算值失败, Err:" + e.Error())
+	//	return
+	//}
+	//periodDataByte, e := json.Marshal(periodData)
+	//if e != nil {
+	//	errMsg = "获取失败"
+	//	err = errors.New("相关性图表, X轴信息有误, Err:" + e.Error())
+	//	return
+	//}
+	//correlationDataByte, e := json.Marshal(correlationData[0].Value)
+	//if e != nil {
+	//	errMsg = "获取失败"
+	//	err = errors.New("相关性图表, Y轴信息有误, Err:" + e.Error())
+	//	return
+	//}
+	correlationChart.LeadValue = req.CorrelationChartInfo.LeadValue
+	correlationChart.LeadUnit = req.CorrelationChartInfo.LeadUnit
+	correlationChart.CalculateValue = req.CorrelationChartInfo.CalculateValue
+	correlationChart.CalculateUnit = req.CorrelationChartInfo.CalculateUnit
+	correlationChart.StartDate = startDate
+	correlationChart.EndDate = endDate
+	correlationChart.EdbInfoIdFirst = req.CorrelationChartInfo.EdbInfoIdList[0].EdbInfoId
+	correlationChart.EdbInfoIdSecond = req.CorrelationChartInfo.EdbInfoIdList[1].EdbInfoId
+
+	// 滚动相关性会有日期等信息
+	if chartItem.Source == utils.CHART_SOURCE_ROLLING_CORRELATION {
+		correlationChart.DateType = req.CorrelationChartInfo.DateType
+	}
+	//correlationChart.PeriodData = string(periodDataByte)
+	//correlationChart.CorrelationData = string(correlationDataByte)
+	correlationChart.ModifyTime = time.Now().Local()
+	//correlationUpdateCols := []string{"LeadValue", "LeadUnit", "StartDate", "EndDate", "EdbInfoIdFirst", "EdbInfoIdSecond", "PeriodData","CorrelationData", "ModifyTime"}
+	correlationUpdateCols := []string{"LeadValue", "LeadUnit", "CalculateValue", "CalculateUnit", "DateType", "StartDate", "EndDate", "EdbInfoIdFirst", "EdbInfoIdSecond", "ModifyTime"}
+
+	// 修改图表与指标mapping
+	req.ChartType = 9
+	err = data_manage.EditCorrelationChartInfoAndMapping(&req, edbInfoIdStr, "公历", 6, disableVal, ``,
+		correlationChart, correlationUpdateCols)
+	if err != nil {
+		errMsg = "保存失败"
+		err = errors.New("保存失败,Err:" + err.Error())
+		return
+	}
+
+	resp := new(data_manage.AddChartInfoResp)
+	resp.ChartInfoId = chartItem.ChartInfoId
+	resp.UniqueCode = chartItem.UniqueCode
+	resp.ChartType = req.ChartType
+
+	// 添加指标引用记录
+	_ = data.SaveChartEdbInfoRelation(edbInfoIdArr, chartItem)
+	//添加es数据
+	go data.EsAddOrEditChartInfo(chartItem.ChartInfoId)
+	//修改my eta es数据
+	go data.EsAddOrEditMyChartInfoByChartInfoId(chartItem.ChartInfoId)
+
+	return
+}
+
+// CopyChartInfo 复制图表
+func CopyChartInfo(configId, classifyId int, chartName string, correlationChartInfoReq data_manage.CorrelationChartInfoReq, oldChartInfo *data_manage.ChartInfo, sysUser *system.Admin, lang string) (chartInfo *data_manage.ChartInfo, err error, errMsg string, isSendEmail bool) {
+	configSource := 2
+	isSendEmail = true
+	// 获取相关性图的配置
+	multipleGraphConfigChartMapping, err := data_manage.GetMultipleGraphConfigChartMappingByIdAndSource(configId, configSource)
+	if err != nil {
+		return
+	}
+	multipleGraphConfig, err := data_manage.GetMultipleGraphConfigById(configId)
+	if err != nil {
+		return
+	}
+	multipleGraphConfig.MultipleGraphConfigId = 0
+	err = data_manage.AddMultipleGraphConfig(multipleGraphConfig)
+	if err != nil {
+		return
+	}
+
+	// 添加图
+	addChartReq := data_manage.AddChartInfoReq{
+		ChartClassifyId:      classifyId,
+		ChartName:            chartName,
+		ChartType:            utils.CHART_TYPE_CURVE,
+		Calendar:             "公历",
+		CorrelationChartInfo: correlationChartInfoReq,
+		ChartThemeId:         oldChartInfo.ChartThemeId,
+		SourcesFrom:          oldChartInfo.SourcesFrom,
+		Instructions:         oldChartInfo.Instructions,
+		MarkersLines:         oldChartInfo.MarkersLines,
+		MarkersAreas:         oldChartInfo.MarkersAreas,
+	}
+	chartSource := utils.CHART_SOURCE_CORRELATION // 默认是相关性图
+	chartInfo, err, errMsg, isSendEmail = AddChartInfo(addChartReq, chartSource, sysUser, lang)
+	if err != nil {
+		return
+	}
+
+	// 添加关系
+	multipleGraphConfigChartMapping = &data_manage.MultipleGraphConfigChartMapping{
+		//Id:                    0,
+		MultipleGraphConfigId: multipleGraphConfig.MultipleGraphConfigId,
+		ChartInfoId:           chartInfo.ChartInfoId,
+		Source:                configSource,
+		ModifyTime:            time.Now(),
+		CreateTime:            time.Now(),
+	}
+	err = data_manage.AddMultipleGraphConfigChartMapping(multipleGraphConfigChartMapping)
+	if err != nil {
+		return
+	}
+
+	//添加es数据
+	go data.EsAddOrEditChartInfo(chartInfo.ChartInfoId)
+
+	return
+}
+
+// CalculateCorrelation 计算相关性-获取x轴和y轴
+func CalculateCorrelation(leadValue int, leadUnit, frequencyA, frequencyB string, dataListA, dataListB []*data_manage.EdbDataList) (xEdbIdValue []int, yDataList []data_manage.YData, err error) {
+	xData := make([]int, 0)
+	yData := make([]float64, 0)
+	if leadValue == 0 {
+		xData = append(xData, 0)
+	}
+	if leadValue > 0 {
+		leadMin := 0 - leadValue
+		xLen := 2*leadValue + 1
+		for i := 0; i < xLen; i++ {
+			n := leadMin + i
+			xData = append(xData, n)
+		}
+	}
+
+	// 计算窗口,不包含第一天
+	//startDateTime, _ := time.ParseInLocation(utils.FormatDate, startDate, time.Local)
+	//startDate = startDateTime.AddDate(0, 0, 1).Format(utils.FormatDate)
+
+	//// 2023-03-02 时间序列始终以指标B为基准, 始终是A进行平移
+	//baseEdbInfo := edbInfoMappingB
+	//changeEdbInfo := edbInfoMappingA
+	// 2023-03-17 时间序列始终以指标A为基准, 始终是B进行平移
+	//baseEdbInfo := edbInfoMappingA
+	//changeEdbInfo := edbInfoMappingB
+
+	// 获取时间基准指标在时间区间内的值
+	//aDataList := make([]*data_manage.EdbDataList, 0)
+	//switch baseEdbInfo.EdbInfoCategoryType {
+	//case 0:
+	//	aDataList, err = data_manage.GetEdbDataList(baseEdbInfo.Source, baseEdbInfo.SubSource, baseEdbInfo.EdbInfoId, startDate, endDate)
+	//case 1:
+	//	_, aDataList, _, _, err, _ = data.GetPredictDataListByPredictEdbInfoId(baseEdbInfo.EdbInfoId, startDate, endDate, false)
+	//default:
+	//	err = errors.New("指标base类型异常")
+	//	return
+	//}
+	//
+	//// 获取变频指标所有日期的值, 插值法完善数据
+	//bDataList := make([]*data_manage.EdbDataList, 0)
+	//switch changeEdbInfo.EdbInfoCategoryType {
+	//case 0:
+	//	bDataList, err = data_manage.GetEdbDataList(changeEdbInfo.Source, changeEdbInfo.SubSource, changeEdbInfo.EdbInfoId, "", "")
+	//case 1:
+	//	_, bDataList, _, _, err, _ = data.GetPredictDataListByPredictEdbInfoId(changeEdbInfo.EdbInfoId, "", "", false)
+	//default:
+	//	err = errors.New("指标change类型异常")
+	//	return
+	//}
+	//changeDataMap := make(map[string]float64)
+	//newChangeDataList, e := HandleDataByLinearRegression(bDataList, changeDataMap)
+	//if e != nil {
+	//	err = fmt.Errorf("获取变频指标插值法Map失败, Err: %s", e.Error())
+	//	return
+	//}
+
+	// 2023-03-17 时间序列始终以指标A为基准, 始终是B进行平移
+	baseDataList := make([]*data_manage.EdbDataList, 0)
+	baseDataMap := make(map[string]float64)
+	changeDataList := make([]*data_manage.EdbDataList, 0)
+	changeDataMap := make(map[string]float64)
+
+	// 先把低频指标升频为高频
+	{
+		frequencyIntMap := map[string]int{
+			"日度": 1,
+			"周度": 2,
+			"旬度": 3,
+			"月度": 4,
+			"季度": 5,
+			"年度": 6,
+		}
+
+		// 如果A指标是高频,那么就需要对B指标进行升频
+		if frequencyIntMap[frequencyA] < frequencyIntMap[frequencyB] {
+			tmpNewChangeDataList, e := HandleDataByLinearRegression(dataListB, changeDataMap)
+			if e != nil {
+				err = fmt.Errorf("获取变频指标插值法Map失败, Err: %s", e.Error())
+				return
+			}
+			changeDataList = tmpNewChangeDataList
+			baseDataList = dataListA
+			for _, v := range baseDataList {
+				baseDataMap[v.DataTime] = v.Value
+			}
+
+		} else if frequencyIntMap[frequencyA] > frequencyIntMap[frequencyB] {
+			// 如果B指标是高频,那么就需要对A指标进行升频
+			tmpNewChangeDataList, e := HandleDataByLinearRegression(dataListA, baseDataMap)
+			if e != nil {
+				err = fmt.Errorf("获取变频指标插值法Map失败, Err: %s", e.Error())
+				return
+			}
+			baseDataList = tmpNewChangeDataList
+
+			changeDataList = dataListB
+			for _, v := range changeDataList {
+				changeDataMap[v.DataTime] = v.Value
+			}
+		} else {
+			baseDataList = dataListA
+			for _, v := range baseDataList {
+				baseDataMap[v.DataTime] = v.Value
+			}
+			changeDataList = dataListB
+			for _, v := range changeDataList {
+				changeDataMap[v.DataTime] = v.Value
+			}
+		}
+
+	}
+
+	// 计算不领先也不滞后时的相关系数
+	baseCalculateData := make([]float64, 0)
+	baseDataTimeArr := make([]string, 0)
+	for i := range baseDataList {
+		baseDataTimeArr = append(baseDataTimeArr, baseDataList[i].DataTime)
+		baseCalculateData = append(baseCalculateData, baseDataList[i].Value)
+	}
+
+	//zeroBaseData := make([]float64, 0)
+	//zeroCalculateData := make([]float64, 0)
+	//for i := range baseDataTimeArr {
+	//	tmpBaseVal, ok1 := baseDataMap[baseDataTimeArr[i]]
+	//	tmpCalculateVal, ok2 := changeDataMap[baseDataTimeArr[i]]
+	//	if ok1 && ok2 {
+	//		zeroBaseData = append(zeroBaseData, tmpBaseVal)
+	//		zeroCalculateData = append(zeroCalculateData, tmpCalculateVal)
+	//	}
+	//}
+	//if len(zeroBaseData) != len(zeroCalculateData) {
+	//	err = fmt.Errorf("相关系数两组序列元素数不一致, %d-%d", len(baseCalculateData), len(zeroCalculateData))
+	//	return
+	//}
+	//zeroRatio := utils.CalculateCorrelationByIntArr(zeroBaseData, zeroCalculateData)
+	//if leadValue == 0 {
+	//	yData = append(yData, zeroRatio)
+	//}
+
+	// 计算领先/滞后N期
+	if leadValue > 0 {
+		// 平移变频指标领先/滞后的日期(单位天)
+		moveUnitDays := utils.FrequencyDaysMap[leadUnit]
+
+		for i := range xData {
+			//if xData[i] == 0 {
+			//	yData = append(yData, zeroRatio)
+			//	continue
+			//}
+			xCalculateData := make([]float64, 0)
+			yCalculateData := make([]float64, 0)
+
+			// 平移指定天数
+			mDays := int(moveUnitDays) * xData[i]
+			_, dMap := MoveDataDaysToNewDataList(changeDataList, mDays)
+
+			// 取出对应的基准日期的值
+			for i2 := range baseDataTimeArr {
+				tmpDate := baseDataTimeArr[i2]
+				if yVal, ok := dMap[tmpDate]; ok {
+					xCalculateData = append(xCalculateData, baseCalculateData[i2])
+					yCalculateData = append(yCalculateData, yVal)
+				}
+			}
+			if len(yCalculateData) <= 0 {
+				//err = fmt.Errorf("领先滞后相关系数两组序列元素数不一致, %d-%d", len(baseCalculateData), len(yCalculateData))
+				//return
+				// 领先滞后后,没有可以计算的数据了
+				continue
+			}
+
+			// 公式计算出领先/滞后频度对应点的相关性系数
+			ratio := utils.CalculateCorrelationByIntArr(xCalculateData, yCalculateData)
+			yData = append(yData, ratio)
+		}
+	}
+
+	xEdbIdValue = xData
+	yDataList = make([]data_manage.YData, 0)
+	yDate := "0000-00-00"
+	yDataList = append(yDataList, data_manage.YData{
+		Date:  yDate,
+		Value: yData,
+	})
+	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
+}
+
+// FormatChartEdbInfoMappings 补充指标信息
+func FormatChartEdbInfoMappings(chartInfoId int, mappings []*data_manage.ChartEdbInfoMapping) (edbList []*data_manage.ChartEdbInfoMapping, err error) {
+	edbList = make([]*data_manage.ChartEdbInfoMapping, 0)
+	if len(mappings) == 0 {
+		return
+	}
+
+	for _, v := range mappings {
+		if chartInfoId <= 0 {
+			v.IsAxis = 1
+			v.LeadValue = 0
+			v.LeadUnit = ""
+			v.ChartEdbMappingId = 0
+			v.ChartInfoId = 0
+			v.IsOrder = false
+			v.EdbInfoType = 1
+			v.ChartStyle = ""
+			v.ChartColor = ""
+			v.ChartWidth = 0
+		} else {
+			v.LeadUnitEn = data.GetLeadUnitEn(v.LeadUnit)
+			v.LeadUnitEn = data.GetLeadUnitEn(v.LeadUnit)
+		}
+		v.FrequencyEn = data.GetFrequencyEn(v.Frequency)
+		if v.Unit == `无` {
+			v.Unit = ``
+		}
+		edbList = append(edbList, v)
+	}
+	return
+}