浏览代码

feat:新增商品价格曲线

Roc 2 年之前
父节点
当前提交
3889051e44

+ 288 - 0
controller/chart/chart_common.go

@@ -0,0 +1,288 @@
+package chart
+
+import (
+	"context"
+	"encoding/json"
+	"github.com/gin-gonic/gin"
+	"hongze/hongze_yb/controller/response"
+	"hongze/hongze_yb/global"
+	"hongze/hongze_yb/models/request"
+	responseModel "hongze/hongze_yb/models/response"
+	"hongze/hongze_yb/models/response/chart_info"
+	chartEdbMappingModel "hongze/hongze_yb/models/tables/chart_edb_mapping"
+	chartInfoModel "hongze/hongze_yb/models/tables/chart_info"
+	"hongze/hongze_yb/models/tables/yb_my_chart"
+	"hongze/hongze_yb/services/chart"
+	future_goodServ "hongze/hongze_yb/services/chart/future_good"
+	"hongze/hongze_yb/services/user"
+	"hongze/hongze_yb/utils"
+	"strconv"
+	"strings"
+)
+
+// CommonChartInfoDetailFromUniqueCode 获取图表详情(通用)
+// @Tags 图库模块
+// @Summary  获取图表详情
+// @Description 获取图表详情
+// @Security ApiKeyAuth
+// @Param Authorization	header string true "Bearer 31a165baebe6dec616b1f8f3207b4273"
+// @Accept  json
+// @Product json
+// @Param DateType query string false "时间段:1-00年至今; 2-10年至今; 3-15年至今; 4-21年至今; 5-指定区间; 6-指定年月至今; 7-18年至今; 8-19年至今; 9-20年至今"
+// @Param ClassifyId query string false "图表分类ID"
+// @Success 200 {object} chart_info.ChartInfoDetailResp
+// @failure 400 {string} string "图表详情获取失败"
+// @Router /my_chart/common/detail [get]
+func CommonChartInfoDetailFromUniqueCode(c *gin.Context) {
+	// 图表ID
+	reqChartInfoId := c.DefaultQuery("ChartInfoId", "")
+	if reqChartInfoId == "" {
+		response.Fail("参数有误:图表ID", c)
+		return
+	}
+	chartInfoId, _ := strconv.Atoi(reqChartInfoId)
+	reqMyChartClassifyId := c.DefaultQuery("MyChartClassifyId", "")
+	myChartClassifyId, _ := strconv.Atoi(reqMyChartClassifyId)
+
+	chartInfo := new(chartInfoModel.ChartInfoView)
+	chartInfo, err := chartInfoModel.GetChartInfoViewById(chartInfoId)
+	if err != nil {
+		if err == utils.ErrNoRow {
+			response.FailMsg("图表不存在,请刷新页面", "图表不存在,请刷新页面", c)
+			return
+		}
+		response.FailMsg(`获取失败`, "获取图表信息失败, Err:"+err.Error(), c)
+		return
+	}
+
+	switch chartInfo.Source {
+	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
+	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
+	default:
+		msg := "错误的图表"
+		errMsg := "错误的图表"
+		response.FailMsg(msg, errMsg, c)
+		return
+	}
+
+}
+
+// getFutureGoodChartInfoDetail 获取商品价格曲线图表详情
+func getFutureGoodChartInfoDetail(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
+	chartInfoId := chartInfo.ChartInfoId
+
+	startDate := chartInfo.StartDate
+	endDate := chartInfo.EndDate
+
+	// 兼容日期错误
+	{
+		if strings.Count(startDate, "-") == 1 {
+			startDate = startDate + "-01"
+		}
+		if strings.Count(endDate, "-") == 1 {
+			endDate = endDate + "-01"
+		}
+	}
+
+	edbInfoMapping, err := chartEdbMappingModel.GetEtaEdbChartEdbMapping(chartInfoId)
+	if err != nil {
+		msg = "获取失败"
+		errMsg = "获取图表,现货指标信息失败,Err:" + err.Error()
+		return
+	}
+	futureGoodEdbInfoMapping, err := chartEdbMappingModel.GetFutureGoodEdbChartEdbMapping(chartInfoId)
+	if err != nil {
+		msg = "获取失败"
+		errMsg = "获取图表的期货商品指标信息失败,Err:" + err.Error()
+		return
+	}
+
+	// 商品价格曲线图的一些配置
+	var barConfig request.BarChartInfoReq
+	barChartInfoDateList := make([]request.BarChartInfoDateReq, 0)
+	barChartInfoSort := request.BarChartInfoSortReq{}
+
+	if chartInfo.BarConfig == `` {
+		msg = "商品价格曲线图未配置"
+		errMsg = "商品价格曲线图未配置"
+		return
+	}
+	err = json.Unmarshal([]byte(chartInfo.BarConfig), &barConfig)
+	if err != nil {
+		msg = "商品价格曲线图配置异常"
+		errMsg = "商品价格曲线图配置异常"
+		return
+	}
+
+	barChartInfoDateList = barConfig.DateList
+	barChartInfoSort = barConfig.Sort
+
+	// 获取图表中的指标数据
+	barConfigEdbInfoIdList, edbList, xEdbIdValue, yDataList, sourceArr, err := future_goodServ.GetChartEdbData(chartInfoId, startDate, endDate, edbInfoMapping, futureGoodEdbInfoMapping, barChartInfoDateList, barChartInfoSort)
+	if err != nil {
+		msg = "获取失败"
+		errMsg = "获取图表,指标信息失败,Err:" + err.Error()
+		return
+	}
+	if len(edbList) <= 0 {
+		msg = "商品价格曲线图表指标异常"
+		errMsg = "商品价格曲线图表异常"
+		return
+	}
+
+	sourceArr = append(sourceArr, "弘则研究")
+	chartInfo.ChartSource = strings.Join(sourceArr, ",")
+
+	for _, v := range edbList {
+		// 指标别名
+		if barConfigEdbInfoIdList != nil && len(barConfigEdbInfoIdList) > 0 {
+			for _, reqEdb := range barConfigEdbInfoIdList {
+				if v.EdbInfoId == reqEdb.EdbInfoId {
+					v.EdbAliasName = reqEdb.Name
+					v.EdbAliasNameEn = reqEdb.NameEn
+				}
+			}
+		}
+	}
+	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.XEdbIdValue = xEdbIdValue
+	resp.YDataList = yDataList
+
+	isOk = true
+
+	return
+}
+
+// RefreshFutureGoodChartInfo 刷新商品价格曲线图表信息
+// @Tags 图库模块
+// @Summary  刷新图表信息
+// @Description 刷新图表信息
+// @Security ApiKeyAuth
+// @Param Authorization	header string true "Bearer 31a165baebe6dec616b1f8f3207b4273"
+// @Accept  json
+// @Product json
+// @Param data body chartInfoModel.SaveChartInfoReq true "请求参数"
+// @Success 200 {string} string "操作成功"
+// @failure 400 {string} string "操作失败"
+// @Router /my_chart/future_good/refreshChartInfo [post]
+func RefreshFutureGoodChartInfo(c *gin.Context) {
+	// 参数校验
+	var req chartInfoModel.RefreshChartInfoReq
+	if c.ShouldBind(&req) != nil {
+		response.Fail("参数异常", c)
+		return
+	}
+	chartInfoId := req.ChartInfoId
+	if chartInfoId == 0 {
+		response.Fail("参数有误", c)
+		return
+	}
+
+	//userInfo := user.GetInfoByClaims(c)
+	//ok, _, err := user.GetAdminByUserInfo(userInfo)
+	//if err != nil {
+	//	response.FailMsg("刷新失败", "RefreshChartInfo-获取系统用户信息失败"+err.Error(), c)
+	//	return
+	//}
+	//if !ok {
+	//	// 普通用户刷新频率限制-每个用户/图/天/2次
+	//	cacheKey := utils.HZ_CHART_LIB_DETAIL + "YB_REFRESH_LIMIT_" + strconv.Itoa(chartInfoId) + "_" + strconv.Itoa(int(userInfo.UserID))
+	//	fmt.Println("refreshCacheKey:", cacheKey)
+	//	countUserRefresh, _ := global.Redis.Get(context.TODO(), cacheKey).Int()
+	//	if countUserRefresh >= 2 {
+	//		response.Ok("目前已是最新数据", c)
+	//		return
+	//	}
+	//	countUserRefresh += 1
+	//	now := time.Now()
+	//	today := time.Date(now.Year(), now.Month(), now.Day(), 23, 59, 59, 0, time.Local)
+	//	sub := today.Sub(now)
+	//	_ = global.Redis.SetEX(context.TODO(), cacheKey, countUserRefresh, sub)
+	//}
+
+	// 图表信息校验
+	chartInfo, err := chartInfoModel.GetChartInfoById(chartInfoId)
+	if err != nil {
+		if err == utils.ErrNoRow {
+			response.Fail("图表已被删除,无需刷新", c)
+			return
+		}
+		response.FailMsg("刷新失败", "刷新失败, Err:"+err.Error(), c)
+		return
+	}
+
+	// 刷新图表
+	//if err = chart.ChartInfoRefreshV2(chartInfo.ChartInfoId); err != nil {
+	//	errContent := fmt.Sprint("ErrMsg: 刷新图表关联指标信息失败, " + err.Error())
+	//	if global.CONFIG.Serve.RunMode == "release" {
+	//		go alarm_msg.SendAlarmMsg("刷新图表报错"+time.Now().Format("2006-01-02 15:04:05")+";Err:"+errContent, 3)
+	//		//go services.SendEmail("弘则研报小程序-release-刷新图表报错", errContent, utils.EmailSendToUsers)
+	//	} else {
+	//		global.LOG.Info(errContent)
+	//	}
+	//}
+
+	//清除图表缓存
+	{
+		key := utils.HZ_CHART_LIB_DETAIL + chartInfo.UniqueCode
+		_ = global.Redis.Del(context.TODO(), key)
+	}
+
+	response.OkData("刷新成功", "", c)
+}

+ 175 - 0
controller/chart/chart_info.go

@@ -266,6 +266,181 @@ func GetChartInfoDetail(c *gin.Context) {
 	response.OkData("获取成功", resp, c)
 }
 
+func getChartInfoDetail(chartInfo *chartInfoModel.ChartInfoView, myChartClassifyId int, userInfo user.UserInfo) (resp *chart_info.ChartInfoDetailResp, isOk bool, msg, errMsg string) {
+	// 获取图表信息
+	var err error
+	chartType := chartInfo.ChartType
+	calendar := chartInfo.Calendar
+
+	// 时段筛选
+	dateType := chartInfo.DateType
+	if dateType <= 0 {
+		dateType = 3 // 默认同后台15年至今
+	}
+	var startDate, endDate string
+	switch dateType {
+	case 1:
+		startDate = "2000-01-01"
+	case 2:
+		startDate = "2010-01-01"
+	case 3:
+		startDate = "2015-01-01"
+	case 4:
+		startDate = "2021-01-01"
+	case 5:
+		if startDate == "" && chartInfo.StartDate != "" {
+			startDate = chartInfo.StartDate
+			endDate = chartInfo.EndDate
+		}
+	case 6:
+		if startDate == "" && chartInfo.StartDate != "" {
+			startDate = chartInfo.StartDate
+		}
+	case 7:
+		startDate = "2018-01-01"
+	case 8:
+		startDate = "2019-01-01"
+	case 9:
+		startDate = "2020-01-01"
+	case 11:
+		startDate = "2022-01-01"
+	}
+
+	// 兼容日期错误
+	{
+		if strings.Count(startDate, "-") == 1 {
+			startDate = startDate + "-01"
+		}
+		if strings.Count(endDate, "-") == 1 {
+			endDate = endDate + "-01"
+		}
+	}
+
+	if chartType == 2 {
+		// 季节性图表
+		var seasonStartDate, seasonEndDate string
+		seasonStartDate = chartInfo.SeasonStartDate
+		seasonEndDate = chartInfo.SeasonEndDate
+		if seasonStartDate != "" {
+			startDate = seasonStartDate + "-01-01"
+		} else {
+			fivePre := time.Now().AddDate(-4, 0, 0).Year()
+			startDate = strconv.Itoa(fivePre) + "-01-01"
+		}
+		if seasonEndDate != "" {
+			endDate = seasonEndDate + "-12-31"
+		} else {
+			endDate = time.Now().Format(utils.FormatDate)
+		}
+	}
+
+	// 获取图表指标映射
+	mappingList := make([]*chartEdbMappingModel.ChartEdbInfoMapping, 0)
+	mappingList, err = chartEdbMappingModel.GetMappingListByChartInfoId(chartInfo.ChartInfoId)
+	if err != nil {
+		msg = `获取失败`
+		errMsg = "获取图表指标信息失败4001, Err:" + err.Error()
+		return
+	}
+
+	//fmt.Println("start_date:", startDate)
+	//fmt.Println("end_date:", endDate)
+
+	// 柱方图的一些配置
+	var barConfig request.BarChartInfoReq
+	barChartInfoDateList := make([]request.BarChartInfoDateReq, 0)
+	barChartInfoSort := request.BarChartInfoSortReq{}
+	if chartInfo != nil && chartInfo.ChartType == 7 {
+		if chartInfo.BarConfig == `` {
+			msg = `柱方图未配置`
+			errMsg = `柱方图未配置`
+			return
+		}
+
+		err := json.Unmarshal([]byte(chartInfo.BarConfig), &barConfig)
+		if err != nil {
+			msg = `柱方图配置异常`
+			errMsg = `柱方图配置异常`
+			return
+		}
+
+		barChartInfoDateList = barConfig.DateList
+		barChartInfoSort = barConfig.Sort
+
+		// 指标别名
+		for _, v := range mappingList {
+			for _, confEdb := range barConfig.EdbInfoIdList {
+				if v.EdbInfoId == confEdb.EdbInfoId {
+					v.EdbAliasName = confEdb.Name
+				}
+			}
+		}
+	}
+	// 获取图表中的指标数据
+	edbList, xEdbIdValue, yDataList, sourceArr, err := chart.GetChartEdbData(chartInfo.ChartInfoId, chartType, calendar, startDate, endDate, mappingList, barChartInfoDateList, barChartInfoSort)
+	if err != nil {
+		msg = `获取失败`
+		errMsg = "获取图表,指标信息失败, Err:" + err.Error()
+		return
+	}
+
+	for _, v := range edbList {
+		// 指标别名
+		if barConfig.EdbInfoIdList != nil && len(barConfig.EdbInfoIdList) > 0 {
+			for _, reqEdb := range barConfig.EdbInfoIdList {
+				if v.EdbInfoId == reqEdb.EdbInfoId {
+					v.EdbAliasName = reqEdb.Name
+				}
+			}
+		}
+	}
+
+	sourceArr = append(sourceArr, "弘则研究")
+	chartInfo.ChartSource = strings.Join(sourceArr, ",")
+
+	// 访问记录-仅普通用户记录
+	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 = new(chart_info.ChartInfoDetailResp)
+	resp.ChartInfo = chartInfo
+	resp.EdbInfoList = edbList
+	resp.XEdbIdValue = xEdbIdValue
+	resp.YDataList = yDataList
+	resp.MyChartInfo = myChartInfo
+
+	isOk = true
+
+	return
+}
+
 // RefreshChartInfo 刷新图表信息
 // @Tags 图库模块
 // @Summary  刷新图表信息

+ 2 - 0
models/request/chart.go

@@ -11,6 +11,8 @@ type BarChartInfoReq struct {
 type BarChartInfoEdbItemReq struct {
 	EdbInfoId int    `description:"指标ID"`
 	Name      string `description:"别名"`
+	NameEn    string `description:"英文别名"`
+	Source    int    `description:"1:ETA图库;2:商品价格"`
 }
 
 // BarChartInfoDateReq 柱方图预览请求数据(日期相关)

+ 5 - 4
models/response/chart_info/chart_info.go

@@ -16,8 +16,9 @@ type ChartInfoDetailResp struct {
 
 // YData 柱方图的y轴数据
 type YData struct {
-	Date  string    `description:"数据日期"`
-	Color string    `description:"数据颜色"`
-	Value []float64 `description:"每个指标的值"`
-	Name  string    `description:"别名"`
+	Date   string    `description:"数据日期"`
+	Color  string    `description:"数据颜色"`
+	Value  []float64 `description:"每个指标的值"`
+	Name   string    `description:"别名"`
+	NameEn string    `description:"英文别名"`
 }

+ 26 - 1
models/tables/chart_edb_mapping/query.go

@@ -2,6 +2,7 @@ package chart_edb_mapping
 
 import (
 	"hongze/hongze_yb/global"
+	"hongze/hongze_yb/utils"
 	"time"
 )
 
@@ -12,6 +13,7 @@ type ChartEdbInfoMapping struct {
 	EdbCode           string    `description:"指标编码"`
 	EdbName           string    `description:"指标名称"`
 	EdbAliasName      string    `description:"指标名称(别名)"`
+	EdbAliasNameEn    string    `description:"英文指标名称(别名)"`
 	EdbType           int       `description:"指标类型:1:基础指标,2:计算指标"`
 	Frequency         string    `description:"频率"`
 	Unit              string    `description:"单位"`
@@ -47,7 +49,8 @@ type ChartEdbInfoMapping struct {
 
 type ChartEdbInfoMappingList struct {
 	ChartEdbInfoMapping
-	DataList interface{}
+	DataList   interface{}
+	IsNullData bool `json:"-" description:"是否空数据"`
 }
 
 // GetMappingListByChartInfoId 根据图表ID获取指标映射列表
@@ -68,3 +71,25 @@ func GetMappingListByEdbInfoId(edbInfoStr string) (list []*ChartEdbInfoMapping,
 	err = global.MYSQL["data"].Raw(sql).Scan(&list).Error
 	return
 }
+
+// GetEtaEdbChartEdbMapping       商品曲线图查询对应的普通指标
+func GetEtaEdbChartEdbMapping(chartInfoId int) (item *ChartEdbInfoMappingList, err error) {
+	sql := ` SELECT a.*,b.source_name,b.source,b.edb_code,b.edb_name,b.edb_name_en,b.frequency,b.unit,b.unit_en,b.start_date,b.end_date,b.modify_time,b.latest_date,b.latest_value,b.unique_code,b.edb_info_type AS edb_info_category_type
+             FROM chart_edb_mapping AS a
+			 INNER JOIN edb_info AS b ON a.edb_info_id=b.edb_info_id
+			 WHERE a.chart_info_id=? AND a.source = ?
+             ORDER BY chart_edb_mapping_id ASC `
+	err = global.MYSQL["data"].Raw(sql, chartInfoId, utils.CHART_SOURCE_DEFAULT).First(&item).Error
+	return
+}
+
+// GetFutureGoodEdbChartEdbMapping       商品曲线图查询对应的商品指标
+func GetFutureGoodEdbChartEdbMapping(chartInfoId int) (item *ChartEdbInfoMappingList, err error) {
+	sql := ` SELECT a.*,b.future_good_edb_info_id,b.future_good_edb_code as edb_code,b.future_good_edb_name as edb_name,b.start_date,b.end_date,b.modify_time,b.latest_date,b.latest_value
+             FROM chart_edb_mapping AS a
+			 INNER JOIN future_good_edb_info AS b ON a.edb_info_id=b.future_good_edb_info_id
+			 WHERE a.chart_info_id=? AND a.source = ?
+             ORDER BY chart_edb_mapping_id ASC `
+	err = global.MYSQL["data"].Raw(sql, chartInfoId, utils.CHART_SOURCE_FUTURE_GOOD).First(&item).Error
+	return
+}

+ 3 - 0
models/tables/chart_info/query.go

@@ -36,6 +36,9 @@ type ChartInfoView struct {
 	RightMax          string `description:"图表右侧最大值"`
 	ChartSource       string `description:"图表来源str"`
 	BarConfig         string `description:"柱方图的配置,json数据" json:"-"`
+	ChartNameEn       string `description:"英文图表名称"`
+	UnitEn            string `description:"英文单位名称"`
+	Source            int    `description:"1:ETA图库;2:商品价格"`
 	//ChartClassify     []*chart_classify.ChartClassifyView
 }
 

+ 67 - 0
models/tables/future_good_edb_data/future_good_edb_data.go

@@ -0,0 +1,67 @@
+package future_good_edb_data
+
+import (
+	"time"
+)
+
+// FutureGoodEdbData 期货指标的数据
+type FutureGoodEdbData struct {
+	FutureGoodEdbDataID uint32    `gorm:"primaryKey;column:future_good_edb_data_id;type:int(9) unsigned;not null" json:"-"`
+	FutureGoodEdbInfoID uint32    `gorm:"index:idx_edbid_date;column:future_good_edb_info_id;type:int(9) unsigned" json:"futureGoodEdbInfoId"` // 期货指标id
+	FutureGoodEdbCode   string    `gorm:"index:idx_code_date;column:future_good_edb_code;type:varchar(64)" json:"futureGoodEdbCode"`           // 期货指标code
+	DataTime            time.Time `gorm:"index:idx_code_date;index:idx_edbid_date;column:data_time;type:date" json:"dataTime"`                 // 数据日期
+	TradeCode           string    `gorm:"column:trade_code;type:varchar(64);default:''" json:"tradeCode"`                                      // 证券代码
+	Open                float64   `gorm:"column:open;type:double;not null" json:"open"`                                                        // 开盘价
+	High                float64   `gorm:"column:high;type:double" json:"high"`                                                                 // 最高价
+	Low                 float64   `gorm:"column:low;type:double" json:"low"`                                                                   // 最低价
+	Close               float64   `gorm:"column:close;type:double" json:"close"`                                                               // 收盘价
+	Volume              float64   `gorm:"column:volume;type:double" json:"volume"`                                                             // 成交量
+	Amt                 float64   `gorm:"column:amt;type:double" json:"amt"`                                                                   // 成交额
+	Oi                  float64   `gorm:"column:oi;type:double" json:"oi"`                                                                     // 持仓量
+	Settle              float64   `gorm:"column:settle;type:double" json:"settle"`                                                             // 结算价
+	DataTimestamp       int64     `gorm:"column:data_timestamp;type:bigint(20)" json:"dataTimestamp"`                                          // 数据日期时间戳
+	ModifyTime          time.Time `gorm:"column:modify_time;type:datetime" json:"modifyTime"`                                                  // 数据修改时间
+	CreateTime          time.Time `gorm:"column:create_time;type:timestamp" json:"createTime"`                                                 // 数据创建时间
+}
+
+// TableName get sql table name.获取数据库表名
+func (m *FutureGoodEdbData) TableName() string {
+	return "future_good_edb_data"
+}
+
+// FutureGoodEdbDataColumns get sql column name.获取数据库列名
+var FutureGoodEdbDataColumns = struct {
+	FutureGoodEdbDataID string
+	FutureGoodEdbInfoID string
+	FutureGoodEdbCode   string
+	DataTime            string
+	TradeCode           string
+	Open                string
+	High                string
+	Low                 string
+	Close               string
+	Volume              string
+	Amt                 string
+	Oi                  string
+	Settle              string
+	DataTimestamp       string
+	ModifyTime          string
+	CreateTime          string
+}{
+	FutureGoodEdbDataID: "future_good_edb_data_id",
+	FutureGoodEdbInfoID: "future_good_edb_info_id",
+	FutureGoodEdbCode:   "future_good_edb_code",
+	DataTime:            "data_time",
+	TradeCode:           "trade_code",
+	Open:                "open",
+	High:                "high",
+	Low:                 "low",
+	Close:               "close",
+	Volume:              "volume",
+	Amt:                 "amt",
+	Oi:                  "oi",
+	Settle:              "settle",
+	DataTimestamp:       "data_timestamp",
+	ModifyTime:          "modify_time",
+	CreateTime:          "create_time",
+}

+ 22 - 0
models/tables/future_good_edb_data/query.go

@@ -0,0 +1,22 @@
+package future_good_edb_data
+
+import "hongze/hongze_yb/global"
+
+func GetFutureGoodEdbDataListByDate(futureGoodEdbInfoId int, startDate, endDate string) (list []*FutureGoodEdbData, err error) {
+	var pars []interface{}
+	sql := `SELECT * FROM future_good_edb_data WHERE 1=1 AND future_good_edb_info_id = ? `
+	pars = append(pars, futureGoodEdbInfoId)
+	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 `
+	err = global.MYSQL["data"].Raw(sql, pars...).Scan(&list).Error
+
+	return
+}

+ 65 - 0
models/tables/future_good_edb_info/future_good_edb_info.go

@@ -0,0 +1,65 @@
+package future_good_edb_info
+
+import "time"
+
+// FutureGoodEdbInfo 期货指标
+type FutureGoodEdbInfo struct {
+	FutureGoodEdbInfoID uint64    `gorm:"primaryKey;column:future_good_edb_info_id;type:bigint(9) unsigned;not null" json:"-"`   // 期货指标id
+	FutureGoodEdbCode   string    `gorm:"column:future_good_edb_code;type:varchar(64);default:''" json:"futureGoodEdbCode"`      // 期货指标code
+	FutureGoodEdbName   string    `gorm:"column:future_good_edb_name;type:varchar(64);default:''" json:"futureGoodEdbName"`      // 期货指标名称
+	FutureGoodEdbNameEn string    `gorm:"column:future_good_edb_name_en;type:varchar(64);default:''" json:"futureGoodEdbNameEn"` // 期货指标名称(英文)
+	ParentID            uint32    `gorm:"column:parent_id;type:int(10) unsigned;default:0" json:"parentId"`                      // 上级期货id
+	Exchange            string    `gorm:"column:exchange;type:varchar(32);default:''" json:"exchange"`                           // 所属交易所
+	Month               uint32    `gorm:"column:month;type:int(9) unsigned;default:0" json:"month"`                              // 所属月份
+	StartDate           time.Time `gorm:"column:start_date;type:date" json:"startDate"`                                          // 数据开始日期
+	EndDate             time.Time `gorm:"column:end_date;type:date" json:"endDate"`                                              // 数据结束日期
+	MinValue            float64   `gorm:"column:min_value;type:double;default:0" json:"minValue"`                                // 最小值
+	MaxValue            float64   `gorm:"column:max_value;type:double;default:0" json:"maxValue"`                                // 最大值
+	LatestValue         float64   `gorm:"column:latest_value;type:double;default:0" json:"latestValue"`                          // 数据最新的值
+	LatestDate          time.Time `gorm:"column:latest_date;type:date" json:"latestDate"`                                        // 数据最新的日期
+	ServerURL           string    `gorm:"column:server_url;type:varchar(255);default:''" json:"serverUrl"`                       // 服务器地址
+	ModifyTime          time.Time `gorm:"column:modify_time;type:datetime" json:"modifyTime"`                                    // 最近修改时间
+	CreateTime          time.Time `gorm:"column:create_time;type:timestamp" json:"createTime"`                                   // 创建时间
+}
+
+// TableName get sql table name.获取数据库表名
+func (m *FutureGoodEdbInfo) TableName() string {
+	return "future_good_edb_info"
+}
+
+// FutureGoodEdbInfoColumns get sql column name.获取数据库列名
+var FutureGoodEdbInfoColumns = struct {
+	FutureGoodEdbInfoID string
+	FutureGoodEdbCode   string
+	FutureGoodEdbName   string
+	FutureGoodEdbNameEn string
+	ParentID            string
+	Exchange            string
+	Month               string
+	StartDate           string
+	EndDate             string
+	MinValue            string
+	MaxValue            string
+	LatestValue         string
+	LatestDate          string
+	ServerURL           string
+	ModifyTime          string
+	CreateTime          string
+}{
+	FutureGoodEdbInfoID: "future_good_edb_info_id",
+	FutureGoodEdbCode:   "future_good_edb_code",
+	FutureGoodEdbName:   "future_good_edb_name",
+	FutureGoodEdbNameEn: "future_good_edb_name_en",
+	ParentID:            "parent_id",
+	Exchange:            "exchange",
+	Month:               "month",
+	StartDate:           "start_date",
+	EndDate:             "end_date",
+	MinValue:            "min_value",
+	MaxValue:            "max_value",
+	LatestValue:         "latest_value",
+	LatestDate:          "latest_date",
+	ServerURL:           "server_url",
+	ModifyTime:          "modify_time",
+	CreateTime:          "create_time",
+}

+ 11 - 0
models/tables/future_good_edb_info/query.go

@@ -0,0 +1,11 @@
+package future_good_edb_info
+
+import "hongze/hongze_yb/global"
+
+// GetFutureGoodEdbInfoListByParentId 根据父级ID获取指标数据列表
+func GetFutureGoodEdbInfoListByParentId(parentId int) (list []*FutureGoodEdbInfo, err error) {
+	sql := `SELECT * FROM future_good_edb_info WHERE parent_id = ?  ORDER BY future_good_edb_info_id ASC `
+	err = global.MYSQL["data"].Raw(sql, parentId).Scan(&list).Error
+
+	return
+}

+ 1 - 0
models/tables/my_chart/query.go

@@ -30,6 +30,7 @@ type MyChartList struct {
 	MyChartClassifyName string  `description:"分类名称,多个用英文逗号分割"`
 	MyChartClassifyId   string  `description:"分类id,多个用英文逗号分割"`
 	EdbEndDate          string  `description:"指标最新更新日期"`
+	Source    int    `description:"1:ETA图库;2:商品价格"`
 }
 
 type MyChartView struct {

+ 2 - 0
routers/chart.go

@@ -17,6 +17,7 @@ func InitChart(r *gin.Engine) {
 		rGroup.POST("/editChartInfo", chart.EditChartInfo)
 		rGroup.POST("/refreshChartInfo", chart.RefreshChartInfo)
 		rGroup.GET("/getChartBeforeAndNext", chart.GetChartBeforeAndNext)
+		rGroup.POST("/future_good/refreshChartInfo", chart.RefreshFutureGoodChartInfo)
 	}
 
 	initChart(r)
@@ -34,5 +35,6 @@ func initChart(r *gin.Engine) {
 		rGroup.POST("/editChartInfo", chart.EditChartInfo)
 		rGroup.POST("/refreshChartInfo", chart.RefreshChartInfo)
 		rGroup.GET("/getChartBeforeAndNext", chart.GetChartBeforeAndNext)
+		rGroup.POST("/future_good/refreshChartInfo", chart.RefreshFutureGoodChartInfo)
 	}
 }

+ 1 - 0
routers/my_chart.go

@@ -26,6 +26,7 @@ func InitMyChart(r *gin.Engine) {
 
 	//mcGroupAuth := rg.Group("my_chart/").Use(middleware.Token(), middleware.CheckBaseAuth())
 	mcGroup.GET("detail", chart.GetChartInfoDetail)
+	mcGroup.GET("common/detail", chart.CommonChartInfoDetailFromUniqueCode)
 
 	// 以下接口可能是从iframe发出请求, 所以token被放在入参中处理而不是header里
 	mcGroupNo := rg.Group("my_chart/")

+ 78 - 0
services/chart/future_good/base_future_good_lib.go

@@ -0,0 +1,78 @@
+package future_good
+
+import (
+	"encoding/json"
+	"fmt"
+	"hongze/hongze_yb/global"
+	"hongze/hongze_yb/utils"
+	"io/ioutil"
+	"net/http"
+	"strings"
+)
+
+type RefreshResponse struct {
+	Ret         int
+	Msg         string
+	ErrMsg      string
+	ErrCode     string
+	Data        interface{}
+	Success     bool `description:"true 执行成功,false 执行失败"`
+	IsSendEmail bool `json:"-" description:"true 发送邮件,false 不发送邮件"`
+	IsAddLog    bool `json:"-" description:"true 新增操作日志,false 不新增操作日志" `
+}
+
+// RefreshEdbData 刷新指标数据
+func RefreshEdbData(futureGoodEdbInfoId int, futureGoodEdbCode, startDate string) (resp *RefreshResponse, err error) {
+	param := make(map[string]interface{})
+	param["FutureGoodEdbCode"] = futureGoodEdbCode
+	param["FutureGoodEdbInfoId"] = futureGoodEdbInfoId
+	param["StartDate"] = startDate
+	urlStr := `future_good/refresh`
+	resp, err = postRefreshEdbData(param, urlStr)
+	return
+}
+
+// postRefreshEdbData 刷新指标数据
+func postRefreshEdbData(param map[string]interface{}, urlStr string) (resp *RefreshResponse, err error) {
+	edbLibUrl := ""
+	if global.CONFIG.Serve.RunMode == "release" {
+		edbLibUrl = "http://172.19.173.232:8300/edbapi/"
+	} else {
+		edbLibUrl = "http://8.136.199.33:8300/edbapi/"
+	}
+	postUrl := edbLibUrl + urlStr
+	postData, err := json.Marshal(param)
+	if err != nil {
+		return
+	}
+	result, err := HttpPost(postUrl, string(postData), "application/json")
+	if err != nil {
+		return
+	}
+	//utils.FileLog.Info("postRefreshEdbData:" + postUrl + ";" + string(postData) + ";result:" + string(result))
+	err = json.Unmarshal(result, &resp)
+	if err != nil {
+		return
+	}
+	return resp, nil
+}
+
+func HttpPost(url, postData string, params ...string) ([]byte, error) {
+	body := ioutil.NopCloser(strings.NewReader(postData))
+	client := &http.Client{}
+	req, err := http.NewRequest("POST", url, body)
+	if err != nil {
+		return nil, err
+	}
+	contentType := "application/x-www-form-urlencoded;charset=utf-8"
+	if len(params) > 0 && params[0] != "" {
+		contentType = params[0]
+	}
+	req.Header.Set("Content-Type", contentType)
+	req.Header.Set("authorization", utils.MD5(utils.APP_EDB_LIB_NAME_EN+utils.EDB_LIB_Md5_KEY))
+	resp, err := client.Do(req)
+	defer resp.Body.Close()
+	b, err := ioutil.ReadAll(resp.Body)
+	fmt.Println("HttpPost:" + string(b))
+	return b, err
+}

+ 465 - 0
services/chart/future_good/chart_info.go

@@ -0,0 +1,465 @@
+package future_good
+
+import (
+	"errors"
+	"fmt"
+	"hongze/hongze_yb/models/request"
+	"hongze/hongze_yb/models/response/chart_info"
+	chartEdbMappingModel "hongze/hongze_yb/models/tables/chart_edb_mapping"
+	edbDataModel "hongze/hongze_yb/models/tables/edb_data"
+	"hongze/hongze_yb/models/tables/future_good_edb_data"
+	"hongze/hongze_yb/models/tables/future_good_edb_info"
+	"hongze/hongze_yb/services/chart"
+	"hongze/hongze_yb/utils"
+	"sort"
+	"strconv"
+	"time"
+)
+
+// GetChartEdbData 获取图表的指标数据
+func GetChartEdbData(chartInfoId int, startDate, endDate string, edbInfoMapping, futureGoodEdbInfoMapping *chartEdbMappingModel.ChartEdbInfoMappingList, barChartInfoDateList []request.BarChartInfoDateReq, barChartInfoSort request.BarChartInfoSortReq) (barConfigEdbInfoIdList []request.BarChartInfoEdbItemReq, edbList []*chartEdbMappingModel.ChartEdbInfoMappingList, xEdbIdValue []int, yDataList []chart_info.YData, sourceArr []string, err error) {
+	edbList = make([]*chartEdbMappingModel.ChartEdbInfoMappingList, 0)
+
+	sourceArr = make([]string, 0)
+	if futureGoodEdbInfoMapping == nil {
+		err = errors.New("商品指标未选取")
+		return
+	}
+	if edbInfoMapping == nil {
+		err = errors.New("ETA指标未选取")
+		return
+	}
+	// 指标对应的所有数据
+	edbDataListMap := make(map[int][]*edbDataModel.EdbDataList)
+
+	item := new(chartEdbMappingModel.ChartEdbInfoMappingList)
+	edbInfoMapping.FrequencyEn = chart.GetFrequencyEn(edbInfoMapping.Frequency)
+
+	if edbInfoMapping.Unit == `无` {
+		edbInfoMapping.Unit = ``
+	}
+	if futureGoodEdbInfoMapping.Unit == `无` {
+		futureGoodEdbInfoMapping.Unit = ``
+	}
+
+	if chartInfoId <= 0 {
+		edbInfoMapping.IsAxis = 1
+		edbInfoMapping.LeadValue = 0
+		edbInfoMapping.LeadUnit = ""
+		edbInfoMapping.ChartEdbMappingId = 0
+		edbInfoMapping.ChartInfoId = 0
+		edbInfoMapping.IsOrder = false
+		edbInfoMapping.EdbInfoType = 1
+		edbInfoMapping.ChartStyle = ""
+		edbInfoMapping.ChartColor = ""
+		edbInfoMapping.ChartWidth = 0
+
+		futureGoodEdbInfoMapping.IsAxis = 1
+		futureGoodEdbInfoMapping.LeadValue = 0
+		futureGoodEdbInfoMapping.LeadUnit = ""
+		futureGoodEdbInfoMapping.ChartEdbMappingId = 0
+		futureGoodEdbInfoMapping.ChartInfoId = 0
+		futureGoodEdbInfoMapping.IsOrder = false
+		futureGoodEdbInfoMapping.EdbInfoType = 1
+		futureGoodEdbInfoMapping.ChartStyle = ""
+		futureGoodEdbInfoMapping.ChartColor = ""
+		futureGoodEdbInfoMapping.ChartWidth = 0
+	} else {
+		edbInfoMapping.LeadUnitEn = chart.GetLeadUnitEn(edbInfoMapping.LeadUnit)
+		futureGoodEdbInfoMapping.LeadUnitEn = chart.GetLeadUnitEn(futureGoodEdbInfoMapping.LeadUnit)
+	}
+
+	// 普通的指标数据
+	{
+		dataList := make([]*edbDataModel.EdbDataList, 0)
+
+		dataList, err = edbDataModel.GetEdbDataList(edbInfoMapping.Source, edbInfoMapping.EdbInfoId, startDate, endDate)
+		edbDataListMap[edbInfoMapping.EdbInfoId] = dataList
+		item.DataList = dataList
+
+		edbList = append(edbList, edbInfoMapping)
+
+		barConfigEdbInfoIdList = append(barConfigEdbInfoIdList, request.BarChartInfoEdbItemReq{
+			EdbInfoId: edbInfoMapping.EdbInfoId,
+			//Name:      edbInfoMapping.EdbName,
+			Name:   "现货价",
+			NameEn: "Spot Price",
+			Source: edbInfoMapping.Source,
+		})
+
+		if !utils.InArray(edbInfoMapping.Source, utils.SystemSourceList) { //来源于系统的指标,都展示为弘则研究
+			if !utils.InArray(edbInfoMapping.SourceName, sourceArr) {
+				sourceArr = append(sourceArr, edbInfoMapping.SourceName)
+			}
+		}
+	}
+
+	nowMonth := time.Now().Month()
+	// 获取期货指标以及期货数据
+	futureGoodEdbInfoList, err := future_good_edb_info.GetFutureGoodEdbInfoListByParentId(futureGoodEdbInfoMapping.EdbInfoId)
+	if err != nil {
+		return
+	}
+
+	futureGoodMappingList := make([]*chartEdbMappingModel.ChartEdbInfoMappingList, 0)
+	//当前月份之后的月
+	nextFutureGoodEdbInfoList := make([]*future_good_edb_info.FutureGoodEdbInfo, 0)
+	for k, v := range futureGoodEdbInfoList {
+		// 过滤当前月
+		if int(v.Month) == int(nowMonth) {
+			continue
+		}
+
+		if int(v.Month) < int(nowMonth) {
+			nextFutureGoodEdbInfoList = append(nextFutureGoodEdbInfoList, v)
+			continue
+		}
+		newMappingInfo := &chartEdbMappingModel.ChartEdbInfoMappingList{
+			ChartEdbInfoMapping: chartEdbMappingModel.ChartEdbInfoMapping{
+				EdbInfoId:           int(v.FutureGoodEdbInfoID),
+				SourceName:          v.Exchange,
+				Source:              utils.CHART_SOURCE_FUTURE_GOOD,
+				EdbCode:             v.FutureGoodEdbCode,
+				EdbName:             v.FutureGoodEdbName,
+				EdbAliasName:        v.FutureGoodEdbName,
+				EdbNameEn:           v.FutureGoodEdbNameEn,
+				EdbType:             edbInfoMapping.EdbType,
+				Frequency:           edbInfoMapping.Frequency,
+				FrequencyEn:         edbInfoMapping.FrequencyEn,
+				Unit:                edbInfoMapping.Unit,
+				UnitEn:              edbInfoMapping.UnitEn,
+				StartDate:           v.StartDate.Format(utils.FormatDateTime),
+				EndDate:             v.EndDate.Format(utils.FormatDateTime),
+				ModifyTime:          v.ModifyTime.Format(utils.FormatDateTime),
+				ChartEdbMappingId:   int(v.FutureGoodEdbInfoID),
+				ChartInfoId:         edbInfoMapping.ChartInfoId,
+				MaxData:             v.MaxValue,
+				MinData:             v.MinValue,
+				IsOrder:             edbInfoMapping.IsOrder,
+				IsAxis:              edbInfoMapping.IsAxis,
+				EdbInfoType:         edbInfoMapping.EdbInfoType,
+				EdbInfoCategoryType: edbInfoMapping.EdbInfoCategoryType,
+				LeadValue:           edbInfoMapping.LeadValue,
+				LeadUnit:            edbInfoMapping.LeadUnit,
+				LeadUnitEn:          edbInfoMapping.LeadUnitEn,
+				ChartStyle:          edbInfoMapping.ChartStyle,
+				ChartColor:          edbInfoMapping.ChartColor,
+				PredictChartColor:   edbInfoMapping.PredictChartColor,
+				ChartWidth:          edbInfoMapping.ChartWidth,
+				ChartType:           edbInfoMapping.ChartType,
+				LatestDate:          v.LatestDate,
+				LatestValue:         v.LatestValue,
+				UniqueCode:          futureGoodEdbInfoMapping.UniqueCode + "1" + strconv.Itoa(k),
+				MinValue:            v.MinValue,
+				MaxValue:            v.MaxValue,
+			},
+			DataList:   nil,
+			IsNullData: false,
+		}
+		futureGoodMappingList = append(futureGoodMappingList, newMappingInfo)
+
+		barConfigEdbInfoIdList = append(barConfigEdbInfoIdList, request.BarChartInfoEdbItemReq{
+			EdbInfoId: newMappingInfo.EdbInfoId,
+			Name:      fmt.Sprint("M+", v.Month),
+			NameEn:    fmt.Sprint("M+", v.Month),
+			Source:    newMappingInfo.Source,
+		})
+	}
+
+	//当前月份之前的月
+	for k, v := range nextFutureGoodEdbInfoList {
+		newMappingInfo := &chartEdbMappingModel.ChartEdbInfoMappingList{
+			ChartEdbInfoMapping: chartEdbMappingModel.ChartEdbInfoMapping{
+				EdbInfoId:           int(v.FutureGoodEdbInfoID),
+				SourceName:          v.Exchange,
+				Source:              utils.CHART_SOURCE_FUTURE_GOOD,
+				EdbCode:             v.FutureGoodEdbCode,
+				EdbName:             v.FutureGoodEdbName,
+				EdbAliasName:        v.FutureGoodEdbName,
+				EdbNameEn:           v.FutureGoodEdbNameEn,
+				EdbType:             edbInfoMapping.EdbType,
+				Frequency:           edbInfoMapping.Frequency,
+				FrequencyEn:         edbInfoMapping.FrequencyEn,
+				Unit:                edbInfoMapping.Unit,
+				UnitEn:              edbInfoMapping.UnitEn,
+				StartDate:           v.StartDate.Format(utils.FormatDateTime),
+				EndDate:             v.EndDate.Format(utils.FormatDateTime),
+				ModifyTime:          v.ModifyTime.Format(utils.FormatDateTime),
+				ChartEdbMappingId:   int(v.FutureGoodEdbInfoID),
+				ChartInfoId:         edbInfoMapping.ChartInfoId,
+				MaxData:             v.MaxValue,
+				MinData:             v.MinValue,
+				IsOrder:             edbInfoMapping.IsOrder,
+				IsAxis:              edbInfoMapping.IsAxis,
+				EdbInfoType:         edbInfoMapping.EdbInfoType,
+				EdbInfoCategoryType: edbInfoMapping.EdbInfoCategoryType,
+				LeadValue:           edbInfoMapping.LeadValue,
+				LeadUnit:            edbInfoMapping.LeadUnit,
+				LeadUnitEn:          edbInfoMapping.LeadUnitEn,
+				ChartStyle:          edbInfoMapping.ChartStyle,
+				ChartColor:          edbInfoMapping.ChartColor,
+				PredictChartColor:   edbInfoMapping.PredictChartColor,
+				ChartWidth:          edbInfoMapping.ChartWidth,
+				ChartType:           edbInfoMapping.ChartType,
+				LatestDate:          v.LatestDate,
+				LatestValue:         v.LatestValue,
+				UniqueCode:          futureGoodEdbInfoMapping.UniqueCode + "1" + strconv.Itoa(k),
+				MinValue:            v.MinValue,
+				MaxValue:            v.MaxValue,
+			},
+			DataList:   nil,
+			IsNullData: false,
+		}
+		futureGoodMappingList = append(futureGoodMappingList, newMappingInfo)
+
+		barConfigEdbInfoIdList = append(barConfigEdbInfoIdList, request.BarChartInfoEdbItemReq{
+			EdbInfoId: newMappingInfo.EdbInfoId,
+			Name:      fmt.Sprint("M+", v.Month),
+			NameEn:    fmt.Sprint("M+", v.Month),
+			Source:    newMappingInfo.Source,
+		})
+	}
+	// 获取数据
+	for _, v := range futureGoodMappingList {
+		dataList := make([]*edbDataModel.EdbDataList, 0)
+
+		tmpDataList, tmpErr := future_good_edb_data.GetFutureGoodEdbDataListByDate(v.EdbInfoId, startDate, endDate)
+		if tmpErr != nil {
+			return
+		}
+		for _, tmpData := range tmpDataList {
+			dataList = append(dataList, &edbDataModel.EdbDataList{
+				EdbDataId:     int(tmpData.FutureGoodEdbDataID),
+				EdbInfoId:     int(tmpData.FutureGoodEdbInfoID),
+				DataTime:      tmpData.DataTime.Format(utils.FormatDate),
+				DataTimestamp: tmpData.DataTimestamp,
+				Value:         tmpData.Close,
+			})
+		}
+		edbDataListMap[v.EdbInfoId] = dataList
+		v.DataList = dataList
+	}
+
+	edbList = append(edbList, futureGoodMappingList...)
+	xEdbIdValue, yDataList, err = BarChartData(edbList, edbDataListMap, barChartInfoDateList, barChartInfoSort)
+	return
+}
+
+// BarChartData 柱方图的数据处理
+func BarChartData(mappingList []*chartEdbMappingModel.ChartEdbInfoMappingList, edbDataListMap map[int][]*edbDataModel.EdbDataList, barChartInfoDateList []request.BarChartInfoDateReq, barChartInfoSort request.BarChartInfoSortReq) (edbIdList []int, yDataList []chart_info.YData, err error) {
+	// 指标数据数组(10086:{"2022-12-02":100.01,"2022-12-01":102.3})
+	edbDataMap := make(map[int]map[string]float64)
+	for edbInfoId, edbDataList := range edbDataListMap {
+		edbDateData := make(map[string]float64)
+		for _, edbData := range edbDataList {
+			edbDateData[edbData.DataTime] = edbData.Value
+		}
+		edbDataMap[edbInfoId] = edbDateData
+	}
+
+	// edbIdList 指标展示顺序;x轴的指标顺序
+	edbIdList = make([]int, 0)
+	//Sort int    `description:"排序类型,0:默认,1:升序,2:降序"`
+	dateData := make(map[int]float64)
+	if barChartInfoSort.Sort == 0 {
+		for _, v := range mappingList {
+			edbIdList = append(edbIdList, v.EdbInfoId)
+		}
+	} else {
+		lenBarChartInfoDateList := len(barChartInfoDateList)
+		if barChartInfoSort.DateIndex >= lenBarChartInfoDateList {
+			err = errors.New("排序日期异常")
+			return
+		}
+
+		notDataEdbIdList := make([]int, 0) //没有数据的指标id
+		// 日期配置
+		barChartInfoDate := barChartInfoDateList[barChartInfoSort.DateIndex]
+		for edbInfoId, dataList := range edbDataListMap {
+			if len(dataList) <= 0 {
+				// 没有数据的指标id
+				notDataEdbIdList = append(notDataEdbIdList, edbInfoId)
+				continue
+			}
+			findDate := barChartInfoDate.Date
+			switch barChartInfoDate.Type {
+			case 1: //最新值
+				findDate = dataList[len(dataList)-1].DataTime
+			case 2: //近期几天
+				findDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, dataList[len(dataList)-1].DataTime, time.Local)
+				if tmpErr != nil {
+					err = tmpErr
+					return
+				}
+				findDateTime = findDateTime.AddDate(0, 0, -barChartInfoDate.Value)
+
+				lenData := len(dataList) - 1
+
+				for i := lenData; i >= 0; i-- {
+					currDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, dataList[i].DataTime, time.Local)
+					if tmpErr != nil {
+						err = tmpErr
+						return
+					}
+					if currDateTime.Equal(findDateTime) || currDateTime.Before(findDateTime) {
+						findDate = dataList[i].DataTime
+						break
+					}
+				}
+			case 3: // 固定日期
+				//最早的日期
+				minDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, dataList[0].DataTime, time.Local)
+				if tmpErr != nil {
+					err = tmpErr
+					return
+				}
+				//寻找固定日期的数据
+				findDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, barChartInfoDate.Date, time.Local)
+				if tmpErr != nil {
+					err = tmpErr
+					return
+				}
+				for tmpDateTime := findDateTime; tmpDateTime.After(minDateTime) || tmpDateTime.Equal(minDateTime); tmpDateTime = tmpDateTime.AddDate(0, 0, -1) {
+					tmpDate := tmpDateTime.Format(utils.FormatDate)
+					if _, ok := edbDataMap[edbInfoId][tmpDate]; ok { //如果能找到数据,那么就返回
+						findDate = tmpDate
+						break
+					}
+				}
+			default:
+				err = errors.New(fmt.Sprint("日期类型异常,Type:", barChartInfoDate.Type))
+				return
+			}
+			if tmpValue, ok := edbDataMap[edbInfoId][findDate]; ok {
+				dateData[edbInfoId] = tmpValue
+			} else {
+				// 没有数据的指标id
+				notDataEdbIdList = append(notDataEdbIdList, edbInfoId)
+			}
+		}
+
+		//Sort int    `description:"排序类型,0:默认,1:升序,2:降序"`
+		// 排序
+		dateDataSort := utils.NewMapSorter(dateData)
+		sort.Sort(dateDataSort)
+		if barChartInfoSort.Sort == 1 {
+			// 先将没有数据的指标id放在最前面
+			if len(notDataEdbIdList) > 0 {
+				edbIdList = append(edbIdList, notDataEdbIdList...)
+			}
+			for _, v := range dateDataSort {
+				edbIdList = append(edbIdList, v.Key)
+			}
+		} else {
+			for i := len(dateDataSort) - 1; i >= 0; i-- {
+				edbIdList = append(edbIdList, dateDataSort[i].Key)
+			}
+			// 再将没有数据的指标id放在最后面
+			if len(notDataEdbIdList) > 0 {
+				edbIdList = append(edbIdList, notDataEdbIdList...)
+			}
+		}
+	}
+
+	yDataList = make([]chart_info.YData, 0) //y轴的数据列表
+
+	for _, barChartInfoDate := range barChartInfoDateList {
+		var maxDate time.Time
+
+		findDataList := make([]float64, 0) // 当前日期的数据值
+		for _, edbInfoId := range edbIdList {
+			findDate := barChartInfoDate.Date     //需要的日期值
+			dataList := edbDataListMap[edbInfoId] //指标的所有数据值
+			if len(dataList) <= 0 {
+				// 没有数据的指标id
+				findDataList = append(findDataList, 0)
+				continue
+			}
+			switch barChartInfoDate.Type {
+			case 1: //最新值
+				dataList := edbDataListMap[edbInfoId]
+				findDate = dataList[len(dataList)-1].DataTime
+			case 2: //近期几天
+				findDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, dataList[len(dataList)-1].DataTime, time.Local)
+				if tmpErr != nil {
+					err = tmpErr
+					return
+				}
+				findDateTime = findDateTime.AddDate(0, 0, -barChartInfoDate.Value)
+
+				lenData := len(dataList) - 1
+				for i := lenData; i >= 0; i-- {
+					currDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, dataList[i].DataTime, time.Local)
+					if tmpErr != nil {
+						err = tmpErr
+						return
+					}
+					if currDateTime.Equal(findDateTime) || currDateTime.Before(findDateTime) {
+						findDate = dataList[i].DataTime
+						break
+					}
+				}
+			case 3: // 固定日期
+				//最早的日期
+				minDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, dataList[0].DataTime, time.Local)
+				if tmpErr != nil {
+					err = tmpErr
+					return
+				}
+				//寻找固定日期的数据
+				findDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, barChartInfoDate.Date, time.Local)
+				if tmpErr != nil {
+					err = tmpErr
+					return
+				}
+				for tmpDateTime := findDateTime; tmpDateTime.After(minDateTime) || tmpDateTime.Equal(minDateTime); tmpDateTime = tmpDateTime.AddDate(0, 0, -1) {
+					tmpDate := tmpDateTime.Format(utils.FormatDate)
+					if _, ok := edbDataMap[edbInfoId][tmpDate]; ok { //如果能找到数据,那么就返回
+						findDate = tmpDate
+						break
+					}
+				}
+			default:
+				err = errors.New(fmt.Sprint("日期类型异常,Type:", barChartInfoDate.Type))
+				return
+			}
+			findDateTime, _ := time.ParseInLocation(utils.FormatDate, findDate, time.Local)
+			if maxDate.IsZero() {
+				maxDate = findDateTime
+			} else {
+				if findDateTime.After(maxDate) {
+					maxDate = findDateTime
+				}
+			}
+			if tmpValue, ok := edbDataMap[edbInfoId][findDate]; ok {
+				findDataList = append(findDataList, tmpValue)
+			} else {
+				findDataList = append(findDataList, 0)
+			}
+		}
+		yName := barChartInfoDate.Name
+		yNameEn := barChartInfoDate.Name
+		if yName == `` {
+			if barChartInfoDate.Type == 2 {
+				yName = strconv.Itoa(barChartInfoDate.Value) + "天前"
+				if barChartInfoDate.Value == 1 {
+					yNameEn = strconv.Itoa(barChartInfoDate.Value) + "day ago"
+				} else {
+					yNameEn = strconv.Itoa(barChartInfoDate.Value) + " days ago"
+				}
+			} else {
+				yName = maxDate.Format(utils.FormatDate)
+				yNameEn = maxDate.Format(utils.FormatDate)
+			}
+		}
+		yDataList = append(yDataList, chart_info.YData{
+			Date:   maxDate.Format(utils.FormatDate),
+			Value:  findDataList,
+			Color:  barChartInfoDate.Color,
+			Name:   yName,
+			NameEn: yNameEn,
+		})
+	}
+
+	return
+}

+ 16 - 10
utils/constants.go

@@ -1,6 +1,6 @@
 package utils
 
-//常量定义
+// 常量定义
 const (
 	FormatTime            = "15:04:05"                //时间格式
 	FormatDate            = "2006-01-02"              //日期格式
@@ -16,7 +16,7 @@ const (
 	PageSize30            = 30
 )
 
-//手机号,电子邮箱正则
+// 手机号,电子邮箱正则
 const (
 	RegularMobile = "^((13[0-9])|(14[5|7])|(15([0-3]|[5-9]))|(18[0-9])|(17[0-9])|(16[0-9])|(19[0-9]))\\d{8}$" //手机号码
 	RegularEmail  = `\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*`                                             //匹配电子邮箱
@@ -27,7 +27,7 @@ const (
 	EmailSendToUsers = "317699326@qq.com;984198890@qq.com;hsun@hzinsights.com;xyxie@hzinsights.com"
 )
 
-//聚合短信
+// 聚合短信
 var (
 	JhGnTplId = "65692" //聚合国内模板编码
 	JhGjTplId = "10054" //聚合国内模板编码
@@ -40,7 +40,7 @@ const (
 	key = "zDeESsxsXuionhqSLZYHWcDJ" //全局加密KEY
 )
 
-//数据来源渠道
+// 数据来源渠道
 const (
 	DATA_SOURCE_THS                         = iota + 1 //同花顺
 	DATA_SOURCE_WIND                                   //wind
@@ -81,7 +81,7 @@ const (
 	DATA_SOURCE_CALCULATE_NHCC                         //计算指标(拟合残差)->37
 	DATA_SOURCE_COM_TRADE                              //联合国商品贸易数据->38
 	DATA_SOURCE_PREDICT_CALCULATE_NSZYDPJJS            //预测指标 - N数值移动平均计算 -> 39
-	DATA_SOURCE_CALCULATE_ADJUST                 //数据调整->40
+	DATA_SOURCE_CALCULATE_ADJUST                       //数据调整->40
 )
 
 const (
@@ -98,7 +98,7 @@ const (
 	CHART_PREFIX = "hz_chart"
 )
 
-//数据刷新频率
+// 数据刷新频率
 const (
 	DATA_REFRESH             = 7 //7个单位,日/周/月/季度/年
 	DATA_START_REFRESH_LIMIT = 7 //7个单位,日/周/月/季度/年
@@ -114,7 +114,7 @@ const (
 
 var PermissionFiccClassifyArr = [...]string{"宏观经济", "化工产业", "建材产业", "有色产业"}
 
-//缓存key
+// 缓存key
 const (
 	CACHE_KEY_USER_VIEW = "user_view_record" //用户阅读数据
 )
@@ -124,7 +124,7 @@ const (
 	ES_INDEX_RDDP_REPORT = "research_report_v1" //报告
 )
 
-//EDB_LIB
+// EDB_LIB
 var (
 	APP_EDB_LIB_NAME_EN = "hongze_edb_lib"
 	EDB_LIB_Md5_KEY     = "GuRaB6dY1bXOJcwG"
@@ -136,7 +136,7 @@ const HZ_DEFAULT_AVATAR = "https://hzstatic.hzinsights.com/static/yb_wx/hz_defau
 const HZPHONE = "057187186319" //弘则电话
 const HZ_ADMIN_WX_ACCESS_TOEKN = "hz_admin:wx:access_token:"
 
-//模板消息推送类型
+// 模板消息推送类型
 const (
 	TEMPLATE_MSG_YB_COMMUNITY_QUESTION = 11 //研报问答社区
 	TEMPLATE_MSG_YB_VOICE_BROADCAST    = 20 //研报语音播报
@@ -192,7 +192,7 @@ var SystemSourceList = []int{
 	DATA_SOURCE_CALCULATE_CJJX,              //超季节性->35
 	DATA_SOURCE_CALCULATE_NHCC,              //计算指标(拟合残差)->37
 	DATA_SOURCE_PREDICT_CALCULATE_NSZYDPJJS, //预测指标 - N数值移动平均计算 -> 39
-	DATA_SOURCE_CALCULATE_ADJUST,                 //数据调整->40
+	DATA_SOURCE_CALCULATE_ADJUST,            //数据调整->40
 }
 
 const (
@@ -211,3 +211,9 @@ var REPORT_CHAPTER_TYPE_NAME_MAP = map[string]string{
 }
 
 const ALIYUN_OSS_HOST = "https://hzstatic.hzinsights.com"
+
+// 图表类型
+const (
+	CHART_SOURCE_DEFAULT     = 1
+	CHART_SOURCE_FUTURE_GOOD = 2
+)