Pārlūkot izejas kodu

feat:新增拟合方程图

Roc 1 gadu atpakaļ
vecāks
revīzija
e474ba96ae

+ 115 - 28
controller/chart/chart_common.go

@@ -20,6 +20,7 @@ import (
 	"hongze/hongze_yb/services/chart"
 	"hongze/hongze_yb/services/chart"
 	"hongze/hongze_yb/services/chart/correlation"
 	"hongze/hongze_yb/services/chart/correlation"
 	future_goodServ "hongze/hongze_yb/services/chart/future_good"
 	future_goodServ "hongze/hongze_yb/services/chart/future_good"
+	"hongze/hongze_yb/services/chart/line_equation"
 	"hongze/hongze_yb/services/user"
 	"hongze/hongze_yb/services/user"
 	"hongze/hongze_yb/utils"
 	"hongze/hongze_yb/utils"
 	"io/ioutil"
 	"io/ioutil"
@@ -63,39 +64,20 @@ func CommonChartInfoDetailFromUniqueCode(c *gin.Context) {
 		return
 		return
 	}
 	}
 
 
+	var resp interface{}
+	var isOk bool
+	var msg, errMsg string
 	switch chartInfo.Source {
 	switch chartInfo.Source {
 	case utils.CHART_SOURCE_DEFAULT:
 	case utils.CHART_SOURCE_DEFAULT:
-		resp, isOk, msg, errMsg := getChartInfoDetail(chartInfo, myChartClassifyId, user.GetInfoByClaims(c))
-		if !isOk {
-			response.FailMsg(msg, errMsg, c)
-			return
-		}
-		response.OkData("获取成功", resp, c)
-		return
+		resp, isOk, msg, errMsg = getChartInfoDetail(chartInfo, myChartClassifyId, user.GetInfoByClaims(c))
 	case utils.CHART_SOURCE_FUTURE_GOOD:
 	case utils.CHART_SOURCE_FUTURE_GOOD:
-		resp, isOk, msg, errMsg := getFutureGoodChartInfoDetail(chartInfo, myChartClassifyId, user.GetInfoByClaims(c))
-		if !isOk {
-			response.FailMsg(msg, errMsg, c)
-			return
-		}
-		response.OkData("获取成功", resp, c)
-		return
+		resp, isOk, msg, errMsg = getFutureGoodChartInfoDetail(chartInfo, myChartClassifyId, user.GetInfoByClaims(c))
 	case utils.CHART_SOURCE_FUTURE_GOOD_PROFIT:
 	case utils.CHART_SOURCE_FUTURE_GOOD_PROFIT:
-		resp, isOk, msg, errMsg := getFutureGoodProfitChartInfoDetail(chartInfo, myChartClassifyId, user.GetInfoByClaims(c))
-		if !isOk {
-			response.FailMsg(msg, errMsg, c)
-			return
-		}
-		response.OkData("获取成功", resp, c)
-		return
+		resp, isOk, msg, errMsg = getFutureGoodProfitChartInfoDetail(chartInfo, myChartClassifyId, user.GetInfoByClaims(c))
 	case utils.CHART_SOURCE_CORRELATION, utils.CHART_SOURCE_ROLLING_CORRELATION:
 	case utils.CHART_SOURCE_CORRELATION, utils.CHART_SOURCE_ROLLING_CORRELATION:
-		resp, isOk, msg, errMsg := getCorrelationChartInfoDetail(chartInfo, myChartClassifyId, user.GetInfoByClaims(c))
-		if !isOk {
-			response.FailMsg(msg, errMsg, c)
-			return
-		}
-		response.OkData("获取成功", resp, c)
-		return
+		resp, isOk, msg, errMsg = getCorrelationChartInfoDetail(chartInfo, myChartClassifyId, user.GetInfoByClaims(c))
+	case utils.CHART_SOURCE_LINE_EQUATION:
+		resp, isOk, msg, errMsg = getChartInfoDetailFromUniqueCode(chartInfo, myChartClassifyId, user.GetInfoByClaims(c))
 	default:
 	default:
 		msg := "错误的图表"
 		msg := "错误的图表"
 		errMsg := "错误的图表"
 		errMsg := "错误的图表"
@@ -103,6 +85,14 @@ func CommonChartInfoDetailFromUniqueCode(c *gin.Context) {
 		return
 		return
 	}
 	}
 
 
+	if !isOk {
+		response.FailMsg(msg, errMsg, c)
+		return
+	}
+	response.OkData("获取成功", resp, c)
+
+	return
+
 }
 }
 
 
 // getFutureGoodChartInfoDetail 获取商品价格曲线图表详情
 // getFutureGoodChartInfoDetail 获取商品价格曲线图表详情
@@ -362,6 +352,103 @@ func getFutureGoodProfitChartInfoDetail(chartInfo *chartInfoModel.ChartInfoView,
 	return
 	return
 }
 }
 
 
+// getChartInfoDetailFromUniqueCode 获取拟合方程图表详情
+func getChartInfoDetailFromUniqueCode(chartInfo *chartInfoModel.ChartInfoView, myChartClassifyId int, userInfo user.UserInfo) (resp *chart_info.ChartInfoDetailResp, isOk bool, msg, errMsg string) {
+	resp = new(chart_info.ChartInfoDetailResp)
+	// 获取图表信息
+	var err error
+
+	if chartInfo.ExtraConfig == `` {
+		msg = "获取失败"
+		errMsg = "获取配置信息失败"
+		return
+	}
+	var lineChartInfoConfig request.LineChartInfoReq
+	err = json.Unmarshal([]byte(chartInfo.ExtraConfig), &lineChartInfoConfig)
+	if err != nil {
+		msg = "获取失败"
+		errMsg = "获取图表配置信息失败, Err:" + err.Error()
+		return
+	}
+
+	var getAData, getBData, getR2Data bool
+	switch lineChartInfoConfig.Source {
+	case utils.CHART_MULTIPLE_GRAPH_LINE_EQUATION_ONE:
+		getAData = true
+	case utils.CHART_MULTIPLE_GRAPH_LINE_EQUATION_TWO:
+		getBData = true
+	case utils.CHART_MULTIPLE_GRAPH_LINE_EQUATION_THREE:
+		getR2Data = true
+	}
+
+	edbList, dataResp, sourceArr, err, errMsg := line_equation.GetChartEdbData(chartInfo.ChartInfoId, lineChartInfoConfig, getAData, getBData, getR2Data)
+	if err != nil {
+		if errMsg == `` {
+			errMsg = "获取失败"
+		}
+		return
+	}
+
+	var resultResp interface{}
+	switch lineChartInfoConfig.Source {
+	case utils.CHART_MULTIPLE_GRAPH_LINE_EQUATION_ONE:
+		resultResp = dataResp.AData
+	case utils.CHART_MULTIPLE_GRAPH_LINE_EQUATION_TWO:
+		resultResp = dataResp.BData
+	case utils.CHART_MULTIPLE_GRAPH_LINE_EQUATION_THREE:
+		resultResp = dataResp.R2Data
+	}
+
+	sourceArr = append(sourceArr, "弘则研究")
+	chartInfo.ChartSource = strings.Join(sourceArr, ",")
+
+	baseEdbInfo := edbList[0] //现货指标
+	chartInfo.UnitEn = baseEdbInfo.UnitEn
+
+	// 访问记录-仅普通用户记录
+	ok, _, _ := user.GetAdminByUserInfo(userInfo)
+	if !ok {
+		go chart.SaveChartVisitLog(userInfo, chartInfo, myChartClassifyId)
+	}
+
+	// 用户是否有收藏该图表
+	{
+		ob := new(yb_my_chart.YbMyChart)
+		cond := `user_id = ? AND chart_info_id = ?`
+		pars := make([]interface{}, 0)
+		pars = append(pars, userInfo.UserID, chartInfo.ChartInfoId)
+		exists, e := ob.FetchByCondition(cond, pars)
+		if e != nil && e != utils.ErrNoRow {
+			msg = `操作失败`
+			errMsg = "获取用户图表失败, Err: " + e.Error()
+			return
+		}
+		myChartInfo := new(responseModel.MyChartItem)
+		if exists != nil && exists.MyChartID > 0 {
+			myChartInfo.MyChartID = exists.MyChartID
+			myChartInfo.MyChartClassifyID = exists.MyChartClassifyID
+			myChartInfo.ChartInfoID = exists.ChartInfoID
+			myChartInfo.ChartName = exists.ChartName
+			myChartInfo.UniqueCode = exists.UniqueCode
+			myChartInfo.ChartImage = exists.ChartImage
+			myChartInfo.UserID = exists.UserID
+			myChartInfo.ReportID = exists.ReportID
+			myChartInfo.ReportChapterID = exists.ReportChapterID
+			myChartInfo.CreateTime = utils.TimeTransferString(utils.FormatDateTime, exists.CreateTime)
+		}
+
+		resp.MyChartInfo = myChartInfo
+	}
+
+	resp.ChartInfo = chartInfo
+	resp.EdbInfoList = edbList
+	resp.DataResp = resultResp
+
+	isOk = true
+
+	return
+}
+
 // RefreshFutureGoodChartInfo 刷新商品价格曲线图表信息
 // RefreshFutureGoodChartInfo 刷新商品价格曲线图表信息
 // @Tags 图库模块
 // @Tags 图库模块
 // @Summary  刷新图表信息
 // @Summary  刷新图表信息

+ 10 - 0
models/request/chart.go

@@ -152,3 +152,13 @@ type ChartInfoDateReq struct {
 	Color string `description:"颜色"`
 	Color string `description:"颜色"`
 	Name  string `description:"别名"`
 	Name  string `description:"别名"`
 }
 }
+
+// LineChartInfoReq 线性拟合图表预览请求数据
+type LineChartInfoReq struct {
+	DateType       int    `description:"日期类型"`
+	StartDate      string `description:"开始日期"`
+	EndDate        string `description:"结束日期"`
+	XEdbInfoIdList []int  `description:"X轴的指标id列表"`
+	YEdbInfoIdList []int  `description:"Y轴的指标id列表"`
+	Source         int    `description:"来源,5:斜率图;6:截距图;7:相关性图"`
+}

+ 16 - 0
models/tables/chart_edb_mapping/query.go

@@ -119,3 +119,19 @@ func GetChartEdbMappingByEdbInfoId(edbInfoId int) (item *ChartEdbInfoMapping, er
 	err = global.MYSQL["data"].Raw(sql, edbInfoId).First(&item).Error
 	err = global.MYSQL["data"].Raw(sql, edbInfoId).First(&item).Error
 	return
 	return
 }
 }
+
+// GetChartEdbMappingListByEdbInfoIdList 根据指标id列表获取关联关系
+func GetChartEdbMappingListByEdbInfoIdList(edbIdList []int) (list []*ChartEdbInfoMapping, err error) {
+	num := len(edbIdList)
+	if num <= 0 {
+		return
+	}
+	sql := ` SELECT edb_info_id,source_name,source,edb_code,edb_name,edb_name_en,frequency,unit,unit_en,start_date,end_date,modify_time,latest_date,latest_value,unique_code,edb_info_type AS edb_info_category_type,max_value,min_value
+             FROM edb_info
+			 WHERE edb_info_id IN(` + utils.GetOrmInReplace(num) + `)
+			ORDER BY FIELD(edb_info_id,` + utils.GetOrmInReplace(num) + `)
+              `
+	err = global.MYSQL["data"].Raw(sql, edbIdList, edbIdList).Find(&list).Error
+
+	return
+}

+ 6 - 0
services/chart/chart_info.go

@@ -472,6 +472,12 @@ func GetChartEdbData(chartInfoId, chartType int, calendar, startDate, endDate st
 	return
 	return
 }
 }
 
 
+// GetEdbDataMapList 获取指标最后的基础数据
+func GetEdbDataMapList(chartInfoId, chartType int, calendar, startDate, endDate string, mappingList []*chartEdbMappingModel.ChartEdbInfoMapping) (edbDataListMap map[int][]*edbDataModel.EdbDataList, edbList []*chartEdbMappingModel.ChartEdbInfoMappingList, sourceArr []string, err error) {
+	edbDataListMap, edbList, sourceArr, err = getEdbDataMapList(chartInfoId, chartType, calendar, startDate, endDate, mappingList)
+	return
+}
+
 // getEdbDataMapList 获取指标最后的基础数据
 // getEdbDataMapList 获取指标最后的基础数据
 func getEdbDataMapList(chartInfoId, chartType int, calendar, startDate, endDate string, mappingList []*chartEdbMappingModel.ChartEdbInfoMapping) (edbDataListMap map[int][]*edbDataModel.EdbDataList, edbList []*chartEdbMappingModel.ChartEdbInfoMappingList, sourceArr []string, err error) {
 func getEdbDataMapList(chartInfoId, chartType int, calendar, startDate, endDate string, mappingList []*chartEdbMappingModel.ChartEdbInfoMapping) (edbDataListMap map[int][]*edbDataModel.EdbDataList, edbList []*chartEdbMappingModel.ChartEdbInfoMappingList, sourceArr []string, err error) {
 	// 关联指标来源
 	// 关联指标来源

+ 42 - 0
services/chart/handle_data.go

@@ -77,3 +77,45 @@ func HandleDataByLinearRegression(edbInfoDataList []*edbDataModel.EdbDataList, h
 
 
 	return
 	return
 }
 }
+
+// HandleDataByPreviousData 当前日期无值时,用上一个日期的数据补充当前日期的数据
+func HandleDataByPreviousData(edbInfoDataList []*edbDataModel.EdbDataList, handleDataMap map[string]float64) (err error) {
+	if len(edbInfoDataList) < 2 {
+		return
+	}
+
+	var startEdbInfoData *edbDataModel.EdbDataList
+	for _, v := range edbInfoDataList {
+		handleDataMap[v.DataTime] = v.Value
+
+		// 第一个数据就给过滤了,给后面的试用
+		if startEdbInfoData == nil {
+			startEdbInfoData = v
+			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
+		}
+
+		// 生成对应的值
+		{
+			for i := 1; i < betweenDay; i++ {
+				tmpDataTime := startDataTime.AddDate(0, 0, i)
+				handleDataMap[tmpDataTime.Format(utils.FormatDate)] = startEdbInfoData.Value
+			}
+		}
+
+		startEdbInfoData = v
+	}
+
+	return
+}

+ 330 - 0
services/chart/line_equation/chart_info.go

@@ -0,0 +1,330 @@
+package line_equation
+
+import (
+	"errors"
+	"hongze/hongze_yb/models/request"
+	chartEdbMappingModel "hongze/hongze_yb/models/tables/chart_edb_mapping"
+	edbDataModel "hongze/hongze_yb/models/tables/edb_data"
+	"hongze/hongze_yb/services/chart"
+	"hongze/hongze_yb/utils"
+	"math"
+	"time"
+)
+
+type LineEquationResp struct {
+	AData  LineEquationDataResp
+	BData  LineEquationDataResp
+	R2Data LineEquationDataResp
+}
+
+type LineEquationDataResp struct {
+	MaxData             float64
+	MinData             float64
+	LatestDate          time.Time `description:"真实数据的最后日期"`
+	EdbInfoCategoryType int
+	ChartColor          string
+	ChartStyle          string
+	PredictChartColor   string
+	ChartType           int
+	ChartWidth          int
+	EdbName             string
+	EdbNameEn           string
+	IsAxis              int
+	DataList            []edbDataModel.EdbDataList
+}
+
+// GetChartEdbData 获取图表数据
+func GetChartEdbData(chartInfoId int, lineChartInfoConfig request.LineChartInfoReq, getAData, getBData, getR2Data bool) (edbList []*chartEdbMappingModel.ChartEdbInfoMappingList, dataResp LineEquationResp, sourceArr []string, err error, errMsg string) {
+	// 获取基本信息
+	mappingList, startDate, endDate, err, errMsg := getConfigData(lineChartInfoConfig)
+	if err != nil {
+		return
+	}
+	xEdbInfoIdList := lineChartInfoConfig.XEdbInfoIdList
+	yEdbInfoIdList := lineChartInfoConfig.YEdbInfoIdList
+
+	aLineEquationDataResp := LineEquationDataResp{
+		DataList:          make([]edbDataModel.EdbDataList, 0),
+		MaxData:           0,
+		MinData:           0,
+		ChartColor:        "#00f",
+		ChartStyle:        `spline`,
+		PredictChartColor: `#00f`,
+		ChartType:         0,
+		ChartWidth:        3,
+		EdbName:           `弹性系数`,
+		EdbNameEn:         `elastic coefficient`,
+		IsAxis:            1,
+	}
+	bLineEquationDataResp := LineEquationDataResp{
+		DataList:          make([]edbDataModel.EdbDataList, 0),
+		MaxData:           0,
+		MinData:           0,
+		ChartColor:        "#00f",
+		ChartStyle:        `spline`,
+		PredictChartColor: `#00f`,
+		ChartType:         0,
+		ChartWidth:        3,
+		EdbName:           `截距`,
+		EdbNameEn:         `intercept`,
+		IsAxis:            1,
+	}
+	r2LineEquationDataResp := LineEquationDataResp{
+		DataList:          make([]edbDataModel.EdbDataList, 0),
+		MaxData:           0,
+		MinData:           0,
+		ChartColor:        "#00f",
+		ChartStyle:        `spline`,
+		PredictChartColor: `#00f`,
+		ChartType:         0,
+		ChartWidth:        3,
+		EdbName:           `相关系数`,
+		EdbNameEn:         `coefficient of association`,
+		IsAxis:            1,
+	}
+	edbList = make([]*chartEdbMappingModel.ChartEdbInfoMappingList, 0)
+	dataResp = LineEquationResp{
+		AData:  aLineEquationDataResp,
+		BData:  bLineEquationDataResp,
+		R2Data: r2LineEquationDataResp,
+	}
+
+	var baseEdbInfo *chartEdbMappingModel.ChartEdbInfoMapping
+	// 获取确定以哪个指标的日期作为基准日期
+	{
+		var xEdbInfo, yEdbInfo *chartEdbMappingModel.ChartEdbInfoMapping
+		for _, v := range mappingList {
+			if v.EdbInfoId == xEdbInfoIdList[0] {
+				xEdbInfo = v
+			} else if v.EdbInfoId == yEdbInfoIdList[0] {
+				yEdbInfo = v
+			}
+		}
+		if xEdbInfo == nil {
+			errMsg = `X轴第一个指标异常`
+			err = errors.New(errMsg)
+			return
+		}
+		if yEdbInfo == nil {
+			errMsg = `Y轴第一个指标异常`
+			err = errors.New(errMsg)
+			return
+		}
+
+		// 时间截面规则:按照什么频率来取不同的截面的问题。原则是:按照X轴和Y轴所选择的第一个指标(X和Y分别有一个第一个指标),两个指标中,以低频的那个作为基准。如果X轴和Y轴是同频的,那以Y轴第一个指标的为准。
+		frequencyIntMap := map[string]int{
+			"日度": 1,
+			"周度": 2,
+			"旬度": 3,
+			"月度": 4,
+			"季度": 5,
+			"年度": 6,
+		}
+		// 如果x是高频 或者 x与y是同频的,那么就是Y轴的第一个指标为主
+		if frequencyIntMap[xEdbInfo.Frequency] <= frequencyIntMap[yEdbInfo.Frequency] {
+			baseEdbInfo = yEdbInfo
+		} else {
+			// 否则是X轴的第一个指标是低频
+			baseEdbInfo = xEdbInfo
+		}
+	}
+
+	// 指标对应的所有数据
+	chartType := 1 //1:普通图,2:季节性图
+	calendar := "农历"
+	edbDataListMap, edbList, sourceArr, err := chart.GetEdbDataMapList(chartInfoId, chartType, calendar, startDate, endDate, mappingList)
+	if err != nil {
+		return
+	}
+
+	// 获取所有的日期
+	dateList := make([]string, 0)
+	for _, v := range edbDataListMap[baseEdbInfo.EdbInfoId] {
+		dateList = append(dateList, v.DataTime)
+	}
+
+	// 数据整理
+	// [日期][A指标id:值,B指标id:值]
+	dateEdbMap, err := handleData(baseEdbInfo.EdbInfoId, edbDataListMap)
+	if err != nil {
+		return
+	}
+
+	lenX := len(xEdbInfoIdList)
+
+	for i, date := range dateList {
+		coordinateData := make([]utils.Coordinate, 0)
+		for k := 0; k < lenX; k++ {
+			xVal, ok1 := dateEdbMap[date][xEdbInfoIdList[k]]
+			yVal, ok2 := dateEdbMap[date][yEdbInfoIdList[k]]
+			if !ok1 || !ok2 {
+				continue
+			}
+			tmpCoordinate1 := utils.Coordinate{
+				X: xVal,
+				Y: yVal,
+			}
+			coordinateData = append(coordinateData, tmpCoordinate1)
+		}
+		dataTime, _ := time.ParseInLocation(utils.FormatDate, date, time.Local)
+		timestamp := dataTime.UnixNano() / 1e6
+		// 只有存在两个坐标点的时候,才能去计算线性方程和R平方
+		if len(coordinateData) >= 2 {
+			a, b := utils.GetLinearResult(coordinateData)
+			if !math.IsNaN(a) && !math.IsNaN(b) && !math.IsInf(a, 0) && !math.IsInf(b, 0) {
+				if getAData {
+					dataResp.AData.DataList = append(dataResp.AData.DataList, edbDataModel.EdbDataList{
+						EdbDataId:     i,
+						EdbInfoId:     0,
+						DataTime:      date,
+						DataTimestamp: timestamp,
+						Value:         a,
+					})
+					if dataResp.AData.MinData > a {
+						dataResp.AData.MinData = a
+					}
+					if dataResp.AData.MaxData < a {
+						dataResp.AData.MaxData = a
+					}
+				}
+				if getBData {
+					dataResp.BData.DataList = append(dataResp.BData.DataList, edbDataModel.EdbDataList{
+						EdbDataId:     i,
+						EdbInfoId:     0,
+						DataTime:      date,
+						DataTimestamp: timestamp,
+						Value:         b,
+					})
+					if dataResp.BData.MinData > a {
+						dataResp.BData.MinData = a
+					}
+					if dataResp.BData.MaxData < a {
+						dataResp.BData.MaxData = a
+					}
+				}
+			}
+
+			// 计算R平方
+			if getR2Data {
+				tmpVal := utils.CalculationDecisive(coordinateData)
+				if math.IsNaN(tmpVal) || math.IsInf(tmpVal, 0) {
+					continue
+				}
+				dataResp.R2Data.DataList = append(dataResp.R2Data.DataList, edbDataModel.EdbDataList{
+					EdbDataId:     i,
+					EdbInfoId:     0,
+					DataTime:      date,
+					DataTimestamp: timestamp,
+					Value:         tmpVal,
+				})
+				if dataResp.R2Data.MinData > tmpVal {
+					dataResp.R2Data.MinData = tmpVal
+				}
+				if dataResp.R2Data.MaxData < tmpVal {
+					dataResp.R2Data.MaxData = tmpVal
+				}
+			}
+		}
+	}
+	dataResp.AData.LatestDate = baseEdbInfo.LatestDate
+	dataResp.AData.EdbInfoCategoryType = baseEdbInfo.EdbInfoCategoryType
+	dataResp.BData.LatestDate = baseEdbInfo.LatestDate
+	dataResp.BData.EdbInfoCategoryType = baseEdbInfo.EdbInfoCategoryType
+	dataResp.R2Data.LatestDate = baseEdbInfo.LatestDate
+	dataResp.R2Data.EdbInfoCategoryType = baseEdbInfo.EdbInfoCategoryType
+
+	return
+}
+
+// getConfigData 获取配置数据
+func getConfigData(lineChartInfoConfig request.LineChartInfoReq) (mappingList []*chartEdbMappingModel.ChartEdbInfoMapping, startDate, endDate string, err error, errMsg string) {
+	dateType := lineChartInfoConfig.DateType
+	switch dateType {
+	case 1:
+		startDate = "2000-01-01"
+	case 2:
+		startDate = "2010-01-01"
+	case 3:
+		startDate = "2015-01-01"
+	case 4:
+		//startDate = strconv.Itoa(time.Now().Year()) + "-01-01"
+		startDate = "2021-01-01"
+	case 5:
+		startDate = lineChartInfoConfig.StartDate + "-01"
+		endDate = lineChartInfoConfig.EndDate + "-01"
+	case 6:
+		startDate = lineChartInfoConfig.StartDate + "-01"
+	case 7:
+		startDate = "2018-01-01"
+	case 8:
+		startDate = "2019-01-01"
+	case 9:
+		startDate = "2020-01-01"
+	case 11:
+		startDate = "2022-01-01"
+	}
+
+	//指标数据
+	edbInfoIdList := make([]int, 0)
+	{
+		edbInfoIdMap := make(map[int]int, 0)
+		for _, edbInfoId := range lineChartInfoConfig.XEdbInfoIdList {
+			edbInfoIdMap[edbInfoId] = edbInfoId
+		}
+		for _, edbInfoId := range lineChartInfoConfig.YEdbInfoIdList {
+			edbInfoIdMap[edbInfoId] = edbInfoId
+		}
+		for _, edbInfoId := range edbInfoIdMap {
+			edbInfoIdList = append(edbInfoIdList, edbInfoId)
+		}
+	}
+	mappingList, err = chartEdbMappingModel.GetChartEdbMappingListByEdbInfoIdList(edbInfoIdList)
+	if err != nil {
+		errMsg = `获取失败`
+		err = errors.New("获取图表,指标信息失败,Err:" + err.Error())
+		return
+	}
+
+	return
+}
+
+// handleData 数据处理
+func handleData(baseEdbInfoId int, edbDataListMap map[int][]*edbDataModel.EdbDataList) (dateEdbMap map[string]map[int]float64, err error) {
+	dateEdbMap = make(map[string]map[int]float64) // [日期][A指标id:值,B指标id:值]
+	for edbInfoId, edbDataList := range edbDataListMap {
+		if edbInfoId != baseEdbInfoId {
+			// 用上期的数据补充当期的数据处理
+			handleDataMap := make(map[string]float64)
+			err = chart.HandleDataByPreviousData(edbDataList, handleDataMap)
+			if err != nil {
+				return
+			}
+
+			for date, val := range handleDataMap {
+				item, ok := dateEdbMap[date]
+				if ok {
+					item[edbInfoId] = val
+				} else {
+					item = map[int]float64{
+						edbInfoId: val,
+					}
+				}
+				dateEdbMap[date] = item
+			}
+		} else {
+			for _, edbData := range edbDataList {
+				item, ok := dateEdbMap[edbData.DataTime]
+				if ok {
+					item[edbInfoId] = edbData.Value
+				} else {
+					item = map[int]float64{
+						edbInfoId: edbData.Value,
+					}
+				}
+				dateEdbMap[edbData.DataTime] = item
+			}
+		}
+	}
+
+	return
+}

+ 9 - 0
utils/common.go

@@ -1101,3 +1101,12 @@ func TimeTransferString(format string, t time.Time) string {
 	}
 	}
 	return str
 	return str
 }
 }
+
+// GetOrmInReplace 获取orm的in查询替换?的方法
+func GetOrmInReplace(num int) string {
+	template := make([]string, num)
+	for i := 0; i < num; i++ {
+		template[i] = "?"
+	}
+	return strings.Join(template, ",")
+}

+ 12 - 0
utils/constants.go

@@ -257,6 +257,18 @@ const (
 	CHART_SOURCE_CORRELATION         = 3 // 相关性图表
 	CHART_SOURCE_CORRELATION         = 3 // 相关性图表
 	CHART_SOURCE_ROLLING_CORRELATION = 4 // 滚动相关性图表
 	CHART_SOURCE_ROLLING_CORRELATION = 4 // 滚动相关性图表
 	CHART_SOURCE_FUTURE_GOOD_PROFIT  = 5 // 商品利润曲线
 	CHART_SOURCE_FUTURE_GOOD_PROFIT  = 5 // 商品利润曲线
+	CHART_SOURCE_LINE_EQUATION       = 6 // 拟合方程图表
+)
+
+// 图表类型
+const (
+	CHART_MULTIPLE_GRAPH_CURVE                   = 1 // 曲线图
+	CHART_MULTIPLE_GRAPH_CORRELATION             = 2 // 相关性图
+	CHART_MULTIPLE_GRAPH_ROLLING_CORRELATION_ONE = 3 // 滚动相关性图1
+	CHART_MULTIPLE_GRAPH_ROLLING_CORRELATION_TWO = 4 // 滚动相关性图2
+	CHART_MULTIPLE_GRAPH_LINE_EQUATION_ONE       = 5 // 拟合方程-斜率图
+	CHART_MULTIPLE_GRAPH_LINE_EQUATION_TWO       = 6 // 拟合方程-截距图
+	CHART_MULTIPLE_GRAPH_LINE_EQUATION_THREE     = 7 // 拟合方程-相关性图
 )
 )
 
 
 // 图表样式类型
 // 图表样式类型