Browse Source

Merge branch 'feature/eta1.9.6_chart_series'

hsun 6 months ago
parent
commit
cea44f09b5

+ 149 - 22
models/chart.go

@@ -696,19 +696,19 @@ type SeasonExtraItem struct {
 
 // 自定义右轴指标
 type SeasonRightAxis struct {
-	IndicatorType int    `description:"右轴指标类型 1:左轴指标同比,2:指标库,3:预测指标 "`
-	Style         string `description:"生成样式"`
-	Shape         string `description:"形状"`
-	ChartColor    string `description:"图表颜色"`
-	Size          int    `description:"大小"`
-	Legend        string `description:"图例名称"`
-	NumFormat     int    `description:"数值格式 1:百分比 2:小数"`
-	IsConnected   int    `description:"是否连接 0不连接 1连接"`
-	LineColor     string `description:"线条颜色"`
-	LineWidth     float64    `description:"线条宽度"`
-	LineStyle     string `description:"线条样式"`
-	IsShow        bool   `description:"是否显示"`
-	IsAdd         bool   `description:"是否添加"`
+	IndicatorType int     `description:"右轴指标类型 1:左轴指标同比,2:指标库,3:预测指标 "`
+	Style         string  `description:"生成样式"`
+	Shape         string  `description:"形状"`
+	ChartColor    string  `description:"图表颜色"`
+	Size          int     `description:"大小"`
+	Legend        string  `description:"图例名称"`
+	NumFormat     int     `description:"数值格式 1:百分比 2:小数"`
+	IsConnected   int     `description:"是否连接 0不连接 1连接"`
+	LineColor     string  `description:"线条颜色"`
+	LineWidth     float64 `description:"线条宽度"`
+	LineStyle     string  `description:"线条样式"`
+	IsShow        bool    `description:"是否显示"`
+	IsAdd         bool    `description:"是否添加"`
 }
 
 // 自定义同期上下限
@@ -722,13 +722,13 @@ type MaxMinLimits struct {
 
 // 自定义同期均线
 type SamePeriodAverage struct {
-	Color     string `description:"颜色"`
-	Year      int    `description:"均线取值范围"`
-	Legend    string `description:"图例名称"`
-	LineType  string `description:"线型"`
-	LineWidth float64    `description:"线宽"`
-	IsShow    bool   `description:"是否显示"`
-	IsAdd     bool   `description:"是否添加"`
+	Color     string  `description:"颜色"`
+	Year      int     `description:"均线取值范围"`
+	Legend    string  `description:"图例名称"`
+	LineType  string  `description:"线型"`
+	LineWidth float64 `description:"线宽"`
+	IsShow    bool    `description:"是否显示"`
+	IsAdd     bool    `description:"是否添加"`
 }
 
 // 自定义同期均线
@@ -737,7 +737,7 @@ type SamePeriodAverageResp struct {
 	Year      int                      `description:"均线取值范围"`
 	Legend    string                   `description:"图例名称"`
 	LineType  string                   `description:"线型"`
-	LineWidth float64                      `description:"线宽"`
+	LineWidth float64                  `description:"线宽"`
 	IsShow    bool                     `description:"是否显示"`
 	List      []*SamePeriodAverageData `description:"自定义均线列表"`
 	IsAdd     bool                     `description:"是否添加"`
@@ -822,6 +822,133 @@ type ChartDwCollectReq struct {
 	Token      string
 }
 
+// 截面组合图额外配置
+type ChartSectionExtraConf struct {
+	DateConfList        []*ChartSectionDateConfItem
+	IsHeap              int                      `description:"是否堆积(1.堆积,0不堆积)"`
+	XDataList           []XData                  `description:"横轴名称设置"`
+	UnitList            *ChartSectionCombineUnit `description:"纵轴单位设置"`
+	BaseChartSeriesName string                   `description:"基准系列名称"`
+	SortType            int                      `description:"排序类型,0默认,1升序,2降序"`
+}
+
+// 截面组合图额外配置
+type ChartSectionAllExtraConf struct {
+	ChartSectionExtraConf
+	SeriesList []*ChartSectionSeriesItem
+}
+
+type ChartSectionDateConfItem struct {
+	MoveForward    int    `description:"前移的期数"`
+	EdbInfoId      int    `description:"指标ID"`
+	EdbName        string `description:"指标名称"`
+	EdbNameEn      string `description:"指标名称英文"`
+	EdbInfoType    int    `description:"指标类型"`
+	Frequency      string `description:"频度"`
+	EndDate        string `description:"最新日期"`
+	DateType       int    `description:"日期类型:0 指标日期,1系统日期"`
+	DateConfName   string `description:"引用日期名称"` // 引用日期名称不能重复
+	DateConfNameEn string `description:"引用日期英文名称"`
+	DateChange     []*ChartSectionDateChange
+}
+
+// 截面组合图引用日期配置
+type ChartSectionDateChange struct {
+	Year         int
+	Month        int
+	Day          int
+	Frequency    string `description:"频度变换"`
+	FrequencyDay string `description:"频度的固定日期"`
+	ChangeType   int    `description:"日期变换类型1日期位移,2指定频率"`
+}
+
+// 截面组合图系列配置
+type ChartSectionSeriesItem struct {
+	ChartSeriesId int     `description:"系列ID"`
+	SeriesName    string  `description:"系列名称"` //系列名称不可同名
+	SeriesNameEn  string  `description:"系列英文名称"`
+	ChartStyle    string  `description:"图表类型"`
+	ChartColor    string  `description:"颜色"`
+	ChartWidth    int     `description:"线条大小"`
+	IsPoint       int     `description:"是否用数据点展示(0 否,1是)"`
+	IsNumber      int     `description:"是否用数值展示(0 否,1是)"`
+	IsAxis        int     `description:"1:左轴,0:右轴"`
+	MaxData       float64 `description:"上限"`
+	MinData       float64 `description:"下限"`
+	//IsOrder         bool    `description:"true:正序,false:逆序"`
+	EdbInfoList    []*ChartSectionSeriesEdbConf
+	DataList       []float64
+	NoDataEdbIndex []int
+}
+type ChartSectionSeriesEdbConf struct {
+	ChartSeriesEdbMappingId int `description:"映射ID"`
+	ChartSeriesId           int `description:"系列ID"`
+	//ChartInfoId             int `description:"图表ID"`
+	EdbInfoId    int `description:"指标id"`
+	DateConf     *ChartSectionSeriesDateConfItem
+	EdbName      string `description:"中文别名"`
+	EdbNameEn    string `description:"英文别名"`
+	EdbInfoType  int    `description:"指标类型"`
+	Unit         string `description:"单位"`
+	UnitEn       string `description:"英文单位"`
+	DateConfName string `description:"引用日期名称"`
+	DateConfType int    `description:"日期类型,0指标最新日期, 1引用日期"`
+}
+
+type ChartSectionCombineDataResp struct {
+	DateConfList        []*ChartSectionDateConfItem
+	IsHeap              int                      `description:"是否堆积(1.堆积,0不堆积)"`
+	XDataList           []XData                  `description:"横轴名称设置"`
+	UnitList            *ChartSectionCombineUnit `description:"纵轴单位设置"`
+	BaseChartSeriesName string                   `description:"基准系列名称"`
+	SortType            int                      `description:"排序类型,0默认,1升序,2降序"`
+	SeriesList          []*ChartSectionSeriesItem
+	LeftMin             string `description:"图表左侧最小值"`
+	LeftMax             string `description:"图表左侧最大值"`
+	RightMin            string `description:"图表右侧最小值"`
+	RightMax            string `description:"图表右侧最大值"`
+	Right2Min           string `description:"图表右侧最小值"`
+	Right2Max           string `description:"图表右侧最大值"`
+}
+
+// 系列里的指标日期配置
+type ChartSectionSeriesDateConfItem struct {
+	MoveForward int `description:"前移的期数"`
+	DateChange  []*ChartSectionDateChange
+}
+
+// PreviewSectionCombineChartReq 预览截面组合图的请求
+type PreviewSectionCombineChartReq struct {
+	ChartName       string `description:"图表名称"`
+	ChartClassifyId int    `description:"分类id"`
+	ExtraConfig     string `description:"图表额外配置信息,json字符串"`
+}
+
+type ChartSectionCombineUnit struct {
+	LeftName       string `description:"左轴单位"`
+	LeftNameEn     string `description:"左轴英文单位"`
+	RightName      string `description:"右轴单位"`
+	RightNameEn    string `description:"右轴英文单位"`
+	RightTwoName   string `description:"右2轴单位"`
+	RightTwoNameEn string `description:"右2轴英文单位"`
+}
+
+// 时序组合图额外配置
+type ChartTimeCombineExtraConf struct {
+	IsHeap int `description:"是否堆积(1.堆积,0不堆积)"`
+}
+
+type ChartTimeCombineDataResp struct {
+	IsHeap int `description:"是否堆积(1.堆积,0不堆积)"`
+}
+
+func GetChartInfoById(chartInfoId int) (item *ChartInfo, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT * FROM chart_info WHERE chart_info_id=? `
+	err = o.Raw(sql, chartInfoId).QueryRow(&item)
+	return
+}
+
 type MarkersLine struct {
 	Axis             int             `json:"axis" description:"1左轴 2右轴 3横轴"`
 	AxisName         string          `json:"axisName" description:"轴的名称,例如'左轴'"`
@@ -830,7 +957,7 @@ type MarkersLine struct {
 	Value            string          `json:"value" description:"连线指向的数值,例如'4000'"`
 	FromValue        string          `json:"fromValue" description:"连线的起始点,可以为空"`
 	ToValue          string          `json:"toValue" description:"连线的结束点,可以为空"`
-	LineWidth        float64             `json:"lineWidth" description:"连线的宽度"`
+	LineWidth        float64         `json:"lineWidth" description:"连线的宽度"`
 	DashStyle        string          `json:"dashStyle" description:"连线的虚线样式,例如'ShortDashDot'"`
 	Color            string          `json:"color" description:"连线的颜色"`
 	Text             string          `json:"text" description:"连线旁边显示的文本"`

+ 305 - 0
models/chart_series.go

@@ -0,0 +1,305 @@
+package models
+
+import (
+	"encoding/json"
+	"eta/eta_chart_lib/utils"
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+type ChartSeries struct {
+	ChartSeriesId int       `orm:"column(chart_series_id);pk"`
+	SeriesName    string    `description:"系列名称"`
+	SeriesNameEn  string    `description:"系列英文名称"`
+	ChartInfoId   int       `description:"图表ID"`
+	ChartStyle    string    `description:"图表类型"`
+	ChartColor    string    `description:"颜色"`
+	ChartWidth    int       `description:"线条大小"`
+	IsPoint       int       `description:"是否用数据点展示(0 否,1是)"`
+	IsNumber      int       `description:"是否用数值展示(0 否,1是)"`
+	IsAxis        int       `description:"1:左轴,0:右轴"`
+	MaxData       float64   `description:"上限"`
+	MinData       float64   `description:"下限"`
+	IsOrder       bool      `description:"true:正序,false:逆序"`
+	CreateTime    time.Time `description:"创建时间"`
+	ModifyTime    time.Time `description:"修改时间"`
+}
+
+func (c *ChartSeries) TableName() string {
+	return "chart_series"
+}
+
+func GetChartSeriesByChartInfoId(chartInfoId int) (items []*ChartSeries, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := "SELECT * FROM chart_series WHERE chart_info_id = ?"
+	_, err = o.Raw(sql, chartInfoId).QueryRows(&items)
+	return
+}
+
+// EditChartSeriesAndEdbMapping
+func EditChartSeriesAndEdbMapping(extraConfigStr string, chartInfoId int) (err error) {
+	o := orm.NewOrmUsingDB("data")
+	to, err := o.Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = to.Rollback()
+		} else {
+			_ = to.Commit()
+		}
+	}()
+
+	// 获取已经存在的系列
+	series, err := GetChartSeriesByChartInfoId(chartInfoId)
+	if err != nil {
+		return
+	}
+	//整理成系列map
+	seriesMap := make(map[int]struct{})
+	seriesDeleteMap := make(map[int]struct{})
+	for _, v := range series {
+		seriesMap[v.ChartSeriesId] = struct{}{}
+		seriesDeleteMap[v.ChartSeriesId] = struct{}{}
+	}
+	var sectionExtraConfig ChartSectionAllExtraConf
+	err = json.Unmarshal([]byte(extraConfigStr), &sectionExtraConfig)
+	if err != nil {
+		err = fmt.Errorf("截面组合图配置异常")
+		return
+	}
+
+	// 删除所有的指标映射
+	_, err = o.Raw("DELETE FROM chart_series_edb_mapping WHERE chart_info_id = ?", chartInfoId).Exec()
+	if err != nil {
+		return
+	}
+
+	seriesList := sectionExtraConfig.SeriesList
+	for _, v := range seriesList {
+		seriesId := v.ChartSeriesId
+		tmp := &ChartSeries{
+			ChartSeriesId: v.ChartSeriesId,
+			SeriesName:    v.SeriesName,
+			SeriesNameEn:  v.SeriesNameEn,
+			ChartInfoId:   chartInfoId,
+			ChartStyle:    v.ChartStyle,
+			ChartColor:    v.ChartColor,
+			ChartWidth:    v.ChartWidth,
+			IsPoint:       v.IsPoint,
+			IsNumber:      v.IsNumber,
+			IsAxis:        v.IsAxis,
+			MaxData:       v.MaxData,
+			MinData:       v.MinData,
+			ModifyTime:    time.Now(),
+		}
+		if _, ok := seriesMap[v.ChartSeriesId]; !ok {
+			if seriesId > 0 {
+				err = fmt.Errorf("系列ID错误")
+				return
+			}
+			//新增
+			tmp.CreateTime = time.Now()
+			seriesIdTmp, e := to.Insert(tmp)
+			if e != nil {
+				err = fmt.Errorf("AddChartSeries Err:" + e.Error())
+				return
+			}
+			seriesId = int(seriesIdTmp)
+		} else {
+			//编辑
+			delete(seriesDeleteMap, v.ChartSeriesId)
+			_, e := to.Update(tmp)
+			if e != nil {
+				err = fmt.Errorf("UpdateChartSeries Err:" + e.Error())
+				return
+			}
+		}
+
+		addSeriesEdbList := make([]*ChartSeriesEdbMapping, 0)
+		for _, edbItem := range v.EdbInfoList {
+			dateConfStrByte, e := json.Marshal(edbItem.DateConf)
+			if e != nil {
+				err = e
+				return
+			}
+			dateConfStr := string(dateConfStrByte)
+			edbTmp := &ChartSeriesEdbMapping{
+				ChartSeriesId: seriesId,    //todo 系列ID
+				ChartInfoId:   chartInfoId, //todo 表图ID
+				EdbInfoId:     edbItem.EdbInfoId,
+				//EdbAliasName:            "",
+				//EdbAliasNameEn:          "",
+				DateConfName: edbItem.DateConfName,
+				DateConf:     dateConfStr,
+				DateConfType: edbItem.DateConfType,
+				CreateTime:   time.Now(),
+				ModifyTime:   time.Now(),
+			}
+			addSeriesEdbList = append(addSeriesEdbList, edbTmp)
+		}
+		if len(addSeriesEdbList) > 0 {
+			_, err = to.InsertMulti(len(addSeriesEdbList), addSeriesEdbList)
+			if err != nil {
+				err = fmt.Errorf("AddChartSeries Err:" + err.Error())
+				return
+			}
+		}
+	}
+	//删除旧的系列和ID
+	seriesIds := make([]int, 0)
+	for id, _ := range seriesDeleteMap {
+		seriesIds = append(seriesIds, id)
+	}
+	if len(seriesIds) > 0 {
+		sql := `DELETE FROM chart_series WHERE chart_series_id IN (` + utils.GetOrmInReplace(len(seriesIds)) + `) and chart_info_id=?`
+		_, err = to.Raw(sql, seriesIds, chartInfoId).Exec()
+		if err != nil {
+			err = fmt.Errorf("删除系列失败 Err:" + err.Error())
+			return
+		}
+		sql = `DELETE FROM chart_series_edb_mapping WHERE chart_series_id IN (` + utils.GetOrmInReplace(len(seriesIds)) + `) and chart_info_id=?`
+		_, err = to.Raw(sql, seriesIds, chartInfoId).Exec()
+		if err != nil {
+			err = fmt.Errorf("删除系列指标 Err:" + err.Error())
+			return
+		}
+	}
+
+	return
+}
+
+func AddChartSeriesAndEdbMapping(extraConfigStr string, chartInfoId int) (err error) {
+	o := orm.NewOrmUsingDB("data")
+	to, err := o.Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = to.Rollback()
+		} else {
+			_ = to.Commit()
+		}
+	}()
+
+	var sectionExtraConfig ChartSectionAllExtraConf
+	err = json.Unmarshal([]byte(extraConfigStr), &sectionExtraConfig)
+	if err != nil {
+		err = fmt.Errorf("截面组合图配置异常")
+		return
+	}
+	seriesList := sectionExtraConfig.SeriesList
+	for _, v := range seriesList {
+		tmp := &ChartSeries{
+			SeriesName:   v.SeriesName,
+			SeriesNameEn: v.SeriesNameEn,
+			ChartInfoId:  chartInfoId,
+			ChartStyle:   v.ChartStyle,
+			ChartColor:   v.ChartColor,
+			ChartWidth:   v.ChartWidth,
+			IsPoint:      v.IsPoint,
+			IsNumber:     v.IsNumber,
+			IsAxis:       v.IsAxis,
+			MaxData:      v.MaxData,
+			MinData:      v.MinData,
+			IsOrder:      false, //todo 是否排序
+			CreateTime:   time.Now(),
+			ModifyTime:   time.Now(),
+		}
+		seriesIdTmp, e := to.Insert(tmp)
+		if e != nil {
+			err = fmt.Errorf("AddChartSeries Err:" + e.Error())
+			return
+		}
+		seriesId := int(seriesIdTmp)
+		addSeriesEdbList := make([]*ChartSeriesEdbMapping, 0)
+		for _, edbItem := range v.EdbInfoList {
+			dateConfStrByte, e := json.Marshal(edbItem.DateConf)
+			if e != nil {
+				err = e
+				return
+			}
+			dateConfStr := string(dateConfStrByte)
+			edbTmp := &ChartSeriesEdbMapping{
+				ChartSeriesId: seriesId,    //todo 系列ID
+				ChartInfoId:   chartInfoId, //todo 表图ID
+				EdbInfoId:     edbItem.EdbInfoId,
+				//EdbAliasName:            "",
+				//EdbAliasNameEn:          "",
+				DateConfName: edbItem.DateConfName,
+				DateConfType: edbItem.DateConfType,
+				DateConf:     dateConfStr,
+				CreateTime:   time.Now(),
+				ModifyTime:   time.Now(),
+			}
+			addSeriesEdbList = append(addSeriesEdbList, edbTmp)
+		}
+		if len(addSeriesEdbList) > 0 {
+			_, e = to.InsertMulti(len(addSeriesEdbList), addSeriesEdbList)
+			if e != nil {
+				err = fmt.Errorf("AddChartSeries Err:" + e.Error())
+				return
+			}
+		}
+	}
+	return
+}
+
+func DeleteChartSeriesAndEdbMapping(chartInfoId int) (err error) {
+	o := orm.NewOrmUsingDB("data")
+	to, err := o.Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = to.Rollback()
+		} else {
+			_ = to.Commit()
+		}
+	}()
+
+	sql := ` DELETE FROM chart_series WHERE chart_info_id=? `
+	_, err = to.Raw(sql, chartInfoId).Exec()
+	if err != nil {
+		return
+	}
+	sql = ` DELETE FROM  chart_series_edb_mapping WHERE chart_info_id=? `
+	_, err = to.Raw(sql, chartInfoId).Exec()
+	return
+}
+
+type ChartSectionSeriesValSortAsc []ChartSectionSeriesValSort
+type ChartSectionSeriesValSortDesc []ChartSectionSeriesValSort
+
+type ChartSectionSeriesValSort struct {
+	Index int
+	Value float64
+}
+
+func (s ChartSectionSeriesValSortAsc) Len() int {
+	return len(s)
+}
+
+func (s ChartSectionSeriesValSortAsc) Less(i, j int) bool {
+	return s[i].Value < s[j].Value // 升序排序,如果想要降序则改为 s[i].Value > s[j].Value
+}
+
+func (s ChartSectionSeriesValSortAsc) Swap(i, j int) {
+	s[i], s[j] = s[j], s[i]
+}
+
+func (s ChartSectionSeriesValSortDesc) Len() int {
+	return len(s)
+}
+
+func (s ChartSectionSeriesValSortDesc) Less(i, j int) bool {
+	return s[i].Value > s[j].Value // 升序排序,如果想要降序则改为 s[i].Value > s[j].Value
+}
+
+func (s ChartSectionSeriesValSortDesc) Swap(i, j int) {
+	s[i], s[j] = s[j], s[i]
+}

+ 29 - 0
models/chart_series_edb_mapping.go

@@ -0,0 +1,29 @@
+package models
+
+import (
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+type ChartSeriesEdbMapping struct {
+	ChartSeriesEdbMappingId int       `orm:"column(chart_series_edb_mapping_id);pk"`
+	ChartSeriesId           int       `description:"系列ID"`
+	ChartInfoId             int       `description:"图表ID"`
+	EdbInfoId               int       `description:"指标id"`
+	DateConfName            string    `description:"引用日期配置名称"`
+	DateConfType            int       `description:"日期类型,0指标最新日期, 1引用日期"`
+	DateConf                string    `description:"日期配置名称"`
+	ModifyTime              time.Time `description:"修改时间"`
+	CreateTime              time.Time `description:"创建时间"`
+}
+
+func (c *ChartSeriesEdbMapping) TableName() string {
+	return "chart_series_edb_mapping"
+}
+
+func GetChartSeriesEdbByChartInfoId(chartInfoId int) (items []*ChartSeriesEdbMapping, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := "SELECT * FROM chart_series_edb_mapping WHERE chart_info_id = ?"
+	_, err = o.Raw(sql, chartInfoId).QueryRows(&items)
+	return
+}

+ 615 - 0
services/data/chart_extra_config.go

@@ -0,0 +1,615 @@
+package data
+
+import (
+	"errors"
+	"eta/eta_chart_lib/models"
+	"eta/eta_chart_lib/utils"
+	"fmt"
+	"sort"
+	"strconv"
+	"time"
+)
+
+// GetChartSectionCombineData 截面组合图的数据处理
+func GetChartSectionCombineData(chartInfo *models.ChartInfo, mappingList []*models.ChartEdbInfoMapping, edbDataListMap map[int][]*models.EdbDataList, extraConfig models.ChartSectionAllExtraConf) (edbIdList []int, dataListResp models.ChartSectionCombineDataResp, 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)
+	edbMappingMap := make(map[int]*models.ChartEdbInfoMapping)
+	for _, v := range mappingList {
+		edbIdList = append(edbIdList, v.EdbInfoId)
+		edbMappingMap[v.EdbInfoId] = v
+	}
+	// 确定好截面散点图返回的数据格式
+	// 获取所有的引用日期设置
+	dateConfListMap := make(map[string]*models.ChartSectionDateConfItem)
+	dateConfEdbIds := make([]int, 0)
+	for _, v := range extraConfig.DateConfList {
+		if v.EdbInfoId > 0 {
+			dateConfEdbIds = append(dateConfEdbIds, v.EdbInfoId)
+		}
+		dateConfListMap[v.DateConfName] = v
+	}
+	// 遍历每个系列
+	// 遍历每个指标,根据选中的日期,进行日期变换得到最终的日期,根据最终的日期获取对应的值
+	// 组装数据
+	baseSeries := new(models.ChartSectionSeriesItem) //y轴的系列
+	var firstUnit, leftUnit, rightUnit, right2Unit *models.XData
+	var (
+		LeftMin   float64
+		LeftMax   float64
+		RightMin  float64
+		RightMax  float64
+		Right2Min float64
+		Right2Max float64
+	)
+	seriesDataListMap := make(map[string][]float64)
+	seriesNoDataIndexMap := make(map[string][]int)
+	for _, seriesItem := range extraConfig.SeriesList {
+		var maxDate time.Time
+		var minVal, maxVal float64
+		noDataEdbIndex := make([]int, 0)
+		dataList := make([]float64, len(seriesItem.EdbInfoList))
+		for index, edbConf := range seriesItem.EdbInfoList {
+			edbInfoId := edbConf.EdbInfoId //X轴的指标
+			edbMappingInfo, ok := edbMappingMap[edbInfoId]
+			if !ok {
+				continue
+			}
+			seriesItem.EdbInfoList[index].EdbName = edbMappingInfo.EdbName
+			seriesItem.EdbInfoList[index].EdbNameEn = edbMappingInfo.EdbNameEn
+			seriesItem.EdbInfoList[index].EdbInfoType = edbMappingInfo.EdbInfoCategoryType
+			seriesItem.EdbInfoList[index].Unit = edbMappingInfo.Unit
+			seriesItem.EdbInfoList[index].UnitEn = edbMappingInfo.UnitEn
+			if index == 0 {
+				firstUnit = &models.XData{
+					Name:   edbMappingInfo.Unit,
+					NameEn: edbMappingInfo.UnitEn,
+				}
+			}
+			edbDataList, ok3 := edbDataListMap[edbInfoId]
+			if !ok3 {
+				err = fmt.Errorf("指标%d的日期数据不存在", edbInfoId)
+				return
+			}
+			//日期变换处理,判断用指标的最新日期还是,直接获取引用日期
+			var findDate string
+			if edbConf.DateConfType == 0 {
+				if edbInfoId == 0 {
+					err = fmt.Errorf("请选择指标")
+					return
+				}
+				findDate, err = GetChartSectionSeriesDateByDateChange(edbInfoId, edbDataList, edbConf.DateConf.DateChange, edbConf.DateConf.MoveForward)
+				if err != nil {
+					err = fmt.Errorf("指标%d的日期变换处理失败", edbInfoId)
+					return
+				}
+			} else {
+				// 获取日期配置
+				dateConfItem, ok1 := dateConfListMap[edbConf.DateConfName]
+				if !ok1 {
+					err = fmt.Errorf("引用日期配置不存在")
+					return
+				}
+				// todo 根据日期变换得到最终日期
+				edbDataListTmp := make([]*models.EdbDataList, 0)
+				if dateConfItem.EdbInfoId > 0 {
+					edbDataListTmp, ok1 = edbDataListMap[dateConfItem.EdbInfoId]
+					if !ok1 {
+						err = fmt.Errorf("指标%d的日期数据不存在", dateConfItem.EdbInfoId)
+						return
+					}
+				}
+
+				findDate, err = GetChartSectionSeriesDateByDateChange(dateConfItem.EdbInfoId, edbDataListTmp, dateConfItem.DateChange, dateConfItem.MoveForward)
+				if err != nil {
+					err = fmt.Errorf("指标%d的日期变换处理失败", dateConfItem.EdbInfoId)
+					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 {
+				dataList[index] = tmpValue
+				if index == 0 {
+					minVal = tmpValue
+					maxVal = tmpValue
+				} else {
+					if tmpValue < minVal {
+						minVal = tmpValue
+					}
+					if tmpValue > maxVal {
+						maxVal = tmpValue
+					}
+				}
+			} else {
+				dataList[index] = 0
+				noDataEdbIndex = append(noDataEdbIndex, index)
+				continue
+			}
+		}
+		seriesDataListMap[seriesItem.SeriesName] = dataList
+		seriesNoDataIndexMap[seriesItem.SeriesName] = noDataEdbIndex
+		seriesItem.DataList = dataList
+		seriesItem.MinData = minVal
+		seriesItem.MaxData = maxVal
+		seriesItem.NoDataEdbIndex = noDataEdbIndex
+		if extraConfig.BaseChartSeriesName == seriesItem.SeriesName {
+			baseSeries = seriesItem
+		}
+		if seriesItem.IsAxis == 1 && leftUnit == nil { //左轴,右轴
+			leftUnit = firstUnit
+		} else if seriesItem.IsAxis == 0 && rightUnit == nil {
+			rightUnit = firstUnit
+		} else if seriesItem.IsAxis == 2 && right2Unit == nil {
+			right2Unit = firstUnit
+		}
+
+		//处理上下限
+		var minData, maxData float64
+		for _, d := range seriesItem.DataList {
+			if minData > d {
+				minData = d
+			}
+			if maxData < d {
+				maxData = d
+			}
+		}
+		if seriesItem.IsAxis == 1 {
+			if LeftMin > minData {
+				LeftMin = minData
+			}
+			if LeftMax < maxData {
+				LeftMax = maxData
+			}
+		} else if seriesItem.IsAxis == 0 {
+			if RightMin > minData {
+				RightMin = minData
+			}
+			if RightMax < maxData {
+				RightMax = maxData
+			}
+		} else {
+			if Right2Min > minData {
+				Right2Min = minData
+			}
+			if Right2Max < maxData {
+				Right2Max = maxData
+			}
+		}
+	}
+	// 处理横轴
+	// 遍历基准系列,判断有几个横轴名称
+	if baseSeries == nil {
+		err = fmt.Errorf("基准系列不存在")
+		return
+	}
+	// 处理系列排序
+	if extraConfig.SortType > 0 {
+		newSeriesDataListMap, newSeriesNoDataIndexMap := SortChartSeriesDataSet(baseSeries.SeriesName, baseSeries.DataList, baseSeries.NoDataEdbIndex, seriesDataListMap, seriesNoDataIndexMap, extraConfig.SortType)
+		for k, item := range extraConfig.SeriesList {
+			dataList, ok := newSeriesDataListMap[item.SeriesName]
+			if ok {
+				extraConfig.SeriesList[k].DataList = dataList
+			}
+			noIndex, ok := newSeriesNoDataIndexMap[item.SeriesName]
+			if ok {
+				extraConfig.SeriesList[k].NoDataEdbIndex = noIndex
+			}
+		}
+	}
+
+	xDataList := make([]models.XData, 0)
+	for index, item := range baseSeries.EdbInfoList {
+		if index == 0 {
+			firstUnit = &models.XData{
+				Name:   item.Unit,
+				NameEn: item.UnitEn,
+			}
+		}
+		tmp := models.XData{
+			Name:   item.EdbName,
+			NameEn: item.EdbNameEn,
+		}
+		// 如果已经设置了横轴名称,则用设置的名称替换
+		if len(extraConfig.XDataList) > index {
+			newItem := extraConfig.XDataList[index]
+			if newItem.Name != "" {
+				tmp = newItem
+			}
+		}
+		xDataList = append(xDataList, tmp)
+	}
+	dataListResp.XDataList = xDataList
+
+	unitList := new(models.ChartSectionCombineUnit)
+	if baseSeries.IsAxis == 1 { //左轴,右轴
+		leftUnit = firstUnit
+	} else if baseSeries.IsAxis == 2 {
+		rightUnit = firstUnit
+	} else {
+		right2Unit = firstUnit
+	}
+	if leftUnit != nil {
+		unitList.LeftName = leftUnit.Name
+		unitList.LeftNameEn = leftUnit.NameEn
+	}
+	if rightUnit != nil {
+		unitList.RightName = rightUnit.Name
+		unitList.RightNameEn = rightUnit.NameEn
+	}
+	if right2Unit != nil {
+		unitList.RightTwoName = right2Unit.Name
+		unitList.RightTwoNameEn = right2Unit.NameEn
+	}
+	if extraConfig.UnitList.LeftName != "" {
+		unitList.LeftName = extraConfig.UnitList.LeftName
+		unitList.LeftNameEn = extraConfig.UnitList.LeftNameEn
+	}
+	if extraConfig.UnitList.RightName != "" {
+		unitList.RightName = extraConfig.UnitList.RightName
+		unitList.RightNameEn = extraConfig.UnitList.RightNameEn
+	}
+
+	if extraConfig.UnitList.RightTwoName != "" {
+		unitList.RightTwoName = extraConfig.UnitList.RightTwoName
+		unitList.RightTwoNameEn = extraConfig.UnitList.RightTwoNameEn
+	}
+
+	if chartInfo != nil && chartInfo.MinMaxSave == 1 {
+		dataListResp.LeftMin = chartInfo.LeftMin
+		dataListResp.LeftMax = chartInfo.LeftMax
+		dataListResp.RightMin = chartInfo.RightMin
+		dataListResp.RightMax = chartInfo.RightMax
+		dataListResp.Right2Min = chartInfo.Right2Min
+		dataListResp.Right2Max = chartInfo.Right2Max
+	} else {
+		dataListResp.LeftMin = strconv.FormatFloat(LeftMin, 'f', -1, 64)
+		dataListResp.LeftMax = strconv.FormatFloat(LeftMax, 'f', -1, 64)
+		dataListResp.RightMin = strconv.FormatFloat(RightMin, 'f', -1, 64)
+		dataListResp.RightMax = strconv.FormatFloat(RightMax, 'f', -1, 64)
+		dataListResp.Right2Min = strconv.FormatFloat(Right2Min, 'f', -1, 64)
+		dataListResp.Right2Max = strconv.FormatFloat(Right2Max, 'f', -1, 64)
+	}
+
+	// 查询引用日期里的指标信息
+	/*if len(dateConfEdbIds) > 0 {
+		dateConfEdbList, e := models.GetEdbInfoByIdList(dateConfEdbIds)
+		if e != nil {
+			err = fmt.Errorf("查询引用日期里的指标信息失败,错误信息:%s", e.Error())
+			return
+		}
+		dateConfEdbMap := make(map[int]*models.EdbInfo)
+		for _, dateConfEdb := range dateConfEdbList {
+			dateConfEdbMap[dateConfEdb.EdbInfoId] = dateConfEdb
+		}
+		for i, dateConf := range extraConfig.DateConfList {
+			if dateConf.EdbInfoId > 0 {
+				edbItem, ok := dateConfEdbMap[dateConf.EdbInfoId]
+				if ok {
+					extraConfig.DateConfList[i].EdbName = edbItem.EdbName
+					extraConfig.DateConfList[i].EdbInfoId = edbItem.EdbInfoId
+					extraConfig.DateConfList[i].EdbInfoType = edbItem.EdbInfoType
+					extraConfig.DateConfList[i].Frequency = edbItem.Frequency
+					extraConfig.DateConfList[i].EndDate = edbItem.EndDate
+				}
+
+			}
+		}
+	}*/
+
+	dataListResp.SeriesList = extraConfig.SeriesList
+	dataListResp.DateConfList = extraConfig.DateConfList
+	dataListResp.BaseChartSeriesName = extraConfig.BaseChartSeriesName
+	dataListResp.UnitList = unitList
+	dataListResp.IsHeap = extraConfig.IsHeap
+	dataListResp.SortType = extraConfig.SortType
+	return
+}
+
+// GetChartSectionSeriesDateByDateChange 获取日期变换后的日期edbInfoId 1指标日期,2 系统日期
+func GetChartSectionSeriesDateByDateChange(edbInfoId int, dataList []*models.EdbDataList, dateChange []*models.ChartSectionDateChange, moveForward int) (newDate string, err error) {
+	if edbInfoId > 0 { //指标日期
+		newDate = GetEdbDateByMoveForward(moveForward, dataList)
+	} else {
+		//系统日期
+		newDate = time.Now().Format(utils.FormatDate)
+	}
+	if newDate != "" && len(dateChange) > 0 {
+		newDate, err = HandleChartSectionSeriesDateChange(newDate, dateChange)
+	}
+	return
+}
+
+func GetEdbDateByMoveForward(moveForward int, edbDataList []*models.EdbDataList) (date string) {
+	dateList := make([]string, 0)
+	for _, v := range edbDataList {
+		dateList = append(dateList, v.DataTime)
+	}
+
+	date = GetEdbDateByMoveForwardByDateList(moveForward, dateList)
+	return
+}
+
+func GetEdbDateByMoveForwardByDateList(moveForward int, dateList []string) (date string) {
+	// 根据日期进行排序
+	index := len(dateList) - 1 - moveForward
+	for k, v := range dateList {
+		if k == index {
+			date = v
+			return
+		}
+	}
+	return
+}
+
+// HandleChartSectionSeriesDateChange 处理日期变换
+func HandleChartSectionSeriesDateChange(date string, dateChange []*models.ChartSectionDateChange) (newDate string, err error) {
+	newDate = date
+	if newDate != "" {
+		if len(dateChange) > 0 {
+			var dateTime time.Time
+			dateTime, err = time.ParseInLocation(utils.FormatDate, newDate, time.Local)
+			if err != nil {
+				err = fmt.Errorf("日期解析失败: %s", err.Error())
+				return
+			}
+			for _, v := range dateChange {
+				if v.ChangeType == 1 {
+					dateTime = dateTime.AddDate(v.Year, v.Month, v.Day)
+					newDate = dateTime.Format(utils.FormatDate)
+				} else if v.ChangeType == 2 {
+					newDate, err, _ = handleSystemAppointDateT(dateTime, v.FrequencyDay, v.Frequency)
+					if err != nil {
+						return
+					}
+					dateTime, err = time.ParseInLocation(utils.FormatDate, newDate, time.Local)
+					if err != nil {
+						err = fmt.Errorf("日期解析失败: %s", err.Error())
+						return
+					}
+				}
+			}
+		}
+	}
+
+	return
+}
+
+// handleSystemAppointDateT
+// @Description: 处理系统日期相关的指定频率(所在周/旬/月/季/半年/年的最后/最早一天)
+// @author: Roc
+// @datetime2023-10-27 09:31:35
+// @param Frequency string
+// @param Day string
+// @return date string
+// @return err error
+// @return errMsg string
+func handleSystemAppointDateT(currDate time.Time, appointDay, frequency string) (date string, err error, errMsg string) {
+	//currDate := time.Now()
+	switch frequency {
+	case "本周":
+		day := int(currDate.Weekday())
+		if day == 0 { // 周日
+			day = 7
+		}
+		num := 0
+		switch appointDay {
+		case "周一":
+			num = 1
+		case "周二":
+			num = 2
+		case "周三":
+			num = 3
+		case "周四":
+			num = 4
+		case "周五":
+			num = 5
+		case "周六":
+			num = 6
+		case "周日":
+			num = 7
+		}
+		day = num - day
+		date = currDate.AddDate(0, 0, day).Format(utils.FormatDate)
+	case "本旬":
+		day := currDate.Day()
+		var tmpDate time.Time
+		switch appointDay {
+		case "第一天":
+			if day <= 10 {
+				tmpDate = time.Date(currDate.Year(), currDate.Month(), 1, 0, 0, 0, 0, currDate.Location())
+			} else if day <= 20 {
+				tmpDate = time.Date(currDate.Year(), currDate.Month(), 11, 0, 0, 0, 0, currDate.Location())
+			} else {
+				tmpDate = time.Date(currDate.Year(), currDate.Month(), 21, 0, 0, 0, 0, currDate.Location())
+			}
+		case "最后一天":
+			if day <= 10 {
+				tmpDate = time.Date(currDate.Year(), currDate.Month(), 10, 0, 0, 0, 0, currDate.Location())
+			} else if day <= 20 {
+				tmpDate = time.Date(currDate.Year(), currDate.Month(), 20, 0, 0, 0, 0, currDate.Location())
+			} else {
+				tmpDate = time.Date(currDate.Year(), currDate.Month()+1, 1, 0, 0, 0, 0, currDate.Location()).AddDate(0, 0, -1)
+			}
+		}
+		date = tmpDate.Format(utils.FormatDate)
+	case "本月":
+		var tmpDate time.Time
+		switch appointDay {
+		case "第一天":
+			tmpDate = time.Date(currDate.Year(), currDate.Month(), 1, 0, 0, 0, 0, currDate.Location())
+		case "最后一天":
+			tmpDate = time.Date(currDate.Year(), currDate.Month()+1, 1, 0, 0, 0, 0, currDate.Location()).AddDate(0, 0, -1)
+		}
+		date = tmpDate.Format(utils.FormatDate)
+	case "本季":
+		month := currDate.Month()
+		var tmpDate time.Time
+		switch appointDay {
+		case "第一天":
+			if month <= 3 {
+				tmpDate = time.Date(currDate.Year(), 1, 1, 0, 0, 0, 0, currDate.Location())
+			} else if month <= 6 {
+				tmpDate = time.Date(currDate.Year(), 4, 1, 0, 0, 0, 0, currDate.Location())
+			} else if month <= 9 {
+				tmpDate = time.Date(currDate.Year(), 7, 1, 0, 0, 0, 0, currDate.Location())
+			} else {
+				tmpDate = time.Date(currDate.Year(), 10, 1, 0, 0, 0, 0, currDate.Location())
+			}
+		case "最后一天":
+			if month <= 3 {
+				tmpDate = time.Date(currDate.Year(), 3, 31, 0, 0, 0, 0, currDate.Location())
+			} else if month <= 6 {
+				tmpDate = time.Date(currDate.Year(), 6, 30, 0, 0, 0, 0, currDate.Location())
+			} else if month <= 9 {
+				tmpDate = time.Date(currDate.Year(), 9, 30, 0, 0, 0, 0, currDate.Location())
+			} else {
+				tmpDate = time.Date(currDate.Year(), 12, 31, 0, 0, 0, 0, currDate.Location())
+			}
+		}
+		date = tmpDate.Format(utils.FormatDate)
+	case "本半年":
+		month := currDate.Month()
+		var tmpDate time.Time
+		switch appointDay {
+		case "第一天":
+			if month <= 6 {
+				tmpDate = time.Date(currDate.Year(), 1, 1, 0, 0, 0, 0, currDate.Location())
+			} else {
+				tmpDate = time.Date(currDate.Year(), 7, 1, 0, 0, 0, 0, currDate.Location())
+			}
+		case "最后一天":
+			if month <= 6 {
+				tmpDate = time.Date(currDate.Year(), 6, 30, 0, 0, 0, 0, currDate.Location())
+			} else {
+				tmpDate = time.Date(currDate.Year(), 12, 31, 0, 0, 0, 0, currDate.Location())
+			}
+		}
+		date = tmpDate.Format(utils.FormatDate)
+	case "本年":
+		var tmpDate time.Time
+		switch appointDay {
+		case "第一天":
+			tmpDate = time.Date(currDate.Year(), 1, 1, 0, 0, 0, 0, currDate.Location())
+		case "最后一天":
+			tmpDate = time.Date(currDate.Year(), 12, 31, 0, 0, 0, 0, currDate.Location())
+		}
+		date = tmpDate.Format(utils.FormatDate)
+	default:
+		errMsg = "错误的日期频度:" + frequency
+		err = errors.New(errMsg)
+		return
+	}
+
+	return
+}
+
+// sortTripleDataSet 以第一组数据为基准,排序之后,空数组的位置也要同步变更
+func SortChartSeriesDataSet(baseName string, baseDataList []float64, baseSeriesNoDataIndexList []int, dataListMap map[string][]float64, noDataListIndexMap map[string][]int, asc int) (newDataListMap map[string][]float64, newNoDataListIndexMap map[string][]int) {
+	newDataListMap = make(map[string][]float64)
+	newNoDataListIndexMap = make(map[string][]int)
+
+	indices := make([]int, len(baseDataList))
+	newIndices := make([]int, len(baseDataList)-len(baseSeriesNoDataIndexList))
+	// 初始化indices
+	for i := range indices {
+		indices[i] = i
+	}
+	if len(baseSeriesNoDataIndexList) > 0 { //把空值移动到最右边
+		j := 0
+		for i := range indices {
+			isEmpty := false
+			for _, v := range baseSeriesNoDataIndexList {
+				if i == v {
+					isEmpty = true
+					break
+				}
+			}
+			if isEmpty {
+				continue
+			}
+			newIndices[j] = i
+			j += 1
+		}
+		newIndices = append(newIndices, baseSeriesNoDataIndexList...)
+		// 根据排序后的indices重新排列所有组的数据
+		for i, idx := range newIndices {
+			for k, _ := range dataListMap {
+				if _, ok := newDataListMap[k]; !ok {
+					newDataListMap[k] = make([]float64, len(baseDataList))
+				}
+				if utils.InArrayByInt(noDataListIndexMap[k], idx) { //如果i位置上的数据为空,那么
+					newNoDataListIndexMap[k] = append(newNoDataListIndexMap[k], i)
+				}
+				newDataListMap[k][i] = dataListMap[k][idx]
+			}
+		}
+		dataListMap = newDataListMap
+		noDataListIndexMap = newNoDataListIndexMap
+		newDataListMap = make(map[string][]float64)
+		newNoDataListIndexMap = make(map[string][]int)
+		baseDataList, _ = dataListMap[baseName]
+		//先把空的数据移动到最后面
+		indices = make([]int, len(baseDataList)-len(baseSeriesNoDataIndexList)) //空值不参与排序
+		newIndices = make([]int, len(baseDataList))                             //空值不参与排序
+		// 初始化indices
+		for i := range indices {
+			indices[i] = i
+		}
+
+	}
+	length := len(indices)
+	baseDataSortList := make([]models.ChartSectionSeriesValSort, length)
+	for i, value := range baseDataList {
+		if i < length {
+			baseDataSortList[i] = models.ChartSectionSeriesValSort{Index: i, Value: value}
+		}
+	}
+	if asc == 1 {
+		// 使用sort.Sort进行排序
+		sort.Sort(models.ChartSectionSeriesValSortAsc(baseDataSortList))
+	} else {
+		sort.Sort(models.ChartSectionSeriesValSortDesc(baseDataSortList))
+	}
+
+	for k, v := range baseDataSortList {
+		indices[k] = v.Index
+	}
+
+	for i := range newIndices {
+		if i < length {
+			newIndices[i] = indices[i]
+		} else {
+			newIndices[i] = i
+		}
+	}
+	// 根据排序后的indices重新排列所有组的数据
+	for i, idx := range newIndices {
+		for k, _ := range dataListMap {
+			if _, ok := newDataListMap[k]; !ok {
+				newDataListMap[k] = make([]float64, len(baseDataList))
+			}
+			if utils.InArrayByInt(noDataListIndexMap[k], idx) { //如果i位置上的数据为空,那么
+				newNoDataListIndexMap[k] = append(newNoDataListIndexMap[k], i)
+			}
+			newDataListMap[k][i] = dataListMap[k][idx]
+		}
+	}
+	return
+}

+ 376 - 3
services/data/chart_info.go

@@ -64,11 +64,23 @@ func GetLeadUnitEn(unit string) (unitEn string) {
 // GetChartEdbData 获取图表的指标数据
 func GetChartEdbData(chartInfoId, chartType int, calendar, startDate, endDate string, mappingList []*models.ChartEdbInfoMapping, extraConfigStr, seasonExtraConfig string) (edbList []*models.ChartEdbInfoMapping, xEdbIdValue []int, yDataList []models.YData, dataResp interface{}, err error, errMsg string) {
 	edbList = make([]*models.ChartEdbInfoMapping, 0)
-	// 指标对应的所有数据
 	xEdbIdValue = make([]int, 0)
 	yDataList = make([]models.YData, 0)
+
 	var extraConfig interface{}
 	switch chartType {
+	case 6:
+		var tmpConfig models.ChartTimeCombineExtraConf
+		if extraConfigStr != `` {
+			err = json.Unmarshal([]byte(extraConfigStr), &tmpConfig)
+			if err != nil {
+				errMsg = "雷达图配置异常"
+				err = errors.New(errMsg)
+				return
+			}
+		}
+
+		extraConfig = tmpConfig
 	case 7: // 柱形图
 		var barConfig data_manage.BarChartInfoReq
 		if extraConfigStr == `` {
@@ -96,6 +108,7 @@ func GetChartEdbData(chartInfoId, chartType int, calendar, startDate, endDate st
 			err = errors.New(errMsg)
 			return
 		}
+
 		extraConfig = tmpExtraConfig
 	case utils.CHART_TYPE_RADAR:
 		var barConfig data_manage.RadarChartInfoReq
@@ -111,6 +124,159 @@ func GetChartEdbData(chartInfoId, chartType int, calendar, startDate, endDate st
 			return
 		}
 		extraConfig = barConfig
+	case utils.CHART_TYPE_SECTION_COMBINE:
+		// 预览和详情都走这个接口
+		var sectionExtraConfig models.ChartSectionAllExtraConf
+		if extraConfigStr == `` {
+			errMsg = "截面组合图未配置"
+			err = errors.New(errMsg)
+			return
+		}
+		if chartInfoId > 0 {
+			var sectionExtraConfigTmp models.ChartSectionExtraConf
+			err = json.Unmarshal([]byte(extraConfigStr), &sectionExtraConfigTmp)
+			if err != nil {
+				errMsg = "截面组合图配置异常"
+				err = errors.New(errMsg)
+				return
+			}
+			sectionExtraConfig.XDataList = sectionExtraConfigTmp.XDataList
+			sectionExtraConfig.BaseChartSeriesName = sectionExtraConfigTmp.BaseChartSeriesName
+			sectionExtraConfig.UnitList = sectionExtraConfigTmp.UnitList
+			sectionExtraConfig.DateConfList = sectionExtraConfigTmp.DateConfList
+			sectionExtraConfig.IsHeap = sectionExtraConfigTmp.IsHeap
+			sectionExtraConfig.SortType = sectionExtraConfigTmp.SortType
+			// 查询所有的seriesEdb
+			seriesEdbList, e := models.GetChartSeriesEdbByChartInfoId(chartInfoId)
+			if e != nil {
+				errMsg = "查询seriesEdb失败"
+				err = errors.New(errMsg + e.Error())
+				return
+			}
+			// todo 是否有必要返回单位信息
+			// 组装成map
+			seriesEdbMap := make(map[int][]*models.ChartSectionSeriesEdbConf)
+			for _, v := range seriesEdbList {
+				var dateConf *models.ChartSectionSeriesDateConfItem
+				if v.DateConf != "" {
+					err = json.Unmarshal([]byte(v.DateConf), &dateConf)
+					if err != nil {
+						errMsg = "截面组合图配置异常"
+						err = errors.New(errMsg + err.Error())
+						return
+					}
+				}
+				tmp := &models.ChartSectionSeriesEdbConf{
+					ChartSeriesEdbMappingId: v.ChartSeriesEdbMappingId,
+					ChartSeriesId:           v.ChartSeriesId,
+					//ChartInfoId:             v.ChartInfoId,
+					EdbInfoId:    v.EdbInfoId,
+					DateConf:     dateConf,
+					EdbName:      "",
+					EdbNameEn:    "",
+					Unit:         "",
+					UnitEn:       "",
+					DateConfName: v.DateConfName,
+					DateConfType: v.DateConfType,
+				}
+				seriesEdbMap[v.ChartSeriesId] = append(seriesEdbMap[v.ChartSeriesId], tmp)
+			}
+			//查询series
+			seriesListTmp, e := models.GetChartSeriesByChartInfoId(chartInfoId)
+			if e != nil {
+				errMsg = "查询series失败"
+				err = errors.New(errMsg + e.Error())
+				return
+			}
+			seriesList := make([]*models.ChartSectionSeriesItem, 0)
+			for _, v := range seriesListTmp {
+
+				tmpSeries := &models.ChartSectionSeriesItem{
+					ChartSeriesId: v.ChartSeriesId,
+					SeriesName:    v.SeriesName,
+					SeriesNameEn:  v.SeriesNameEn,
+					ChartStyle:    v.ChartStyle,
+					ChartColor:    v.ChartColor,
+					ChartWidth:    v.ChartWidth,
+					IsPoint:       v.IsPoint,
+					IsNumber:      v.IsNumber,
+					IsAxis:        v.IsAxis,
+					MaxData:       v.MaxData,
+					MinData:       v.MinData,
+					//IsOrder:         false,
+					EdbInfoList: nil,
+					DataList:    nil,
+				}
+				edbInfoList, ok := seriesEdbMap[v.ChartSeriesId]
+				if ok {
+					tmpSeries.EdbInfoList = edbInfoList
+				}
+				seriesList = append(seriesList, tmpSeries)
+			}
+			sectionExtraConfig.SeriesList = seriesList
+
+		} else {
+			err = json.Unmarshal([]byte(extraConfigStr), &sectionExtraConfig)
+			if err != nil {
+				errMsg = "截面组合图配置异常"
+				err = errors.New(errMsg)
+				return
+			}
+		}
+
+		//校验引用日期名称是否重复
+		dateNameMap := make(map[string]int)
+		dateNameEnMap := make(map[string]int)
+		for _, v := range sectionExtraConfig.DateConfList {
+			if _, ok := dateNameMap[v.DateConfName]; ok {
+				errMsg = "截面组合图引用日期名称设置重复"
+				err = errors.New(errMsg + v.DateConfName)
+				return
+			}
+			if _, ok := dateNameEnMap[v.DateConfNameEn]; ok {
+				errMsg = "截面组合图引用日期名称设置重复"
+				err = errors.New(errMsg + v.DateConfNameEn)
+				return
+			}
+			if v.DateConfName != "" {
+				dateNameMap[v.DateConfName] = 1
+			}
+			if v.DateConfNameEn != "" {
+				dateNameEnMap[v.DateConfNameEn] = 1
+			}
+
+		}
+
+		//检查系列名称是否重复
+		seriesNameMap := make(map[string]int)
+		seriesNameEnMap := make(map[string]int)
+		for _, v := range sectionExtraConfig.SeriesList {
+			if _, ok := seriesNameMap[v.SeriesName]; ok {
+				errMsg = "截面组合图系列名称设置重复"
+				err = errors.New(errMsg + v.SeriesName)
+				return
+			}
+			if _, ok := seriesNameEnMap[v.SeriesNameEn]; ok {
+				errMsg = "截面组合图系列名称设置重复"
+				err = errors.New(errMsg + v.SeriesNameEn)
+				return
+			}
+			if v.SeriesName != "" {
+				seriesNameMap[v.SeriesName] = 1
+			}
+			if v.SeriesNameEn != "" {
+				seriesNameEnMap[v.SeriesNameEn] = 1
+			}
+		}
+
+		// 检查基准系列是否设置
+		if sectionExtraConfig.BaseChartSeriesName == "" {
+			errMsg = "截面组合图基准系列名称未设置"
+			err = errors.New(errMsg)
+			return
+		}
+		//todo 如果是详情接口,应该要从其他表里查询配置
+		extraConfig = sectionExtraConfig
 	default:
 		xEdbIdValue = make([]int, 0)
 		yDataList = make([]models.YData, 0)
@@ -137,6 +303,15 @@ func GetChartEdbData(chartInfoId, chartType int, calendar, startDate, endDate st
 			// 兼容无配置的老图
 			dataResp = new(models.SeasonChartResp)
 		}
+	case 6: //时序组合图
+		//判断是否堆积
+		timeConf := extraConfig.(models.ChartTimeCombineExtraConf)
+		if extraConfigStr == "" { //历史数据,默认开启堆积
+			timeConf = models.ChartTimeCombineExtraConf{
+				IsHeap: 1,
+			}
+		}
+		dataResp = models.ChartTimeCombineDataResp{IsHeap: timeConf.IsHeap}
 	case 7: // 柱形图
 		barChartConf := extraConfig.(data_manage.BarChartInfoReq)
 		xEdbIdValue, yDataList, err = BarChartData(mappingList, edbDataListMap, barChartConf.DateList, barChartConf.Sort)
@@ -154,6 +329,18 @@ func GetChartEdbData(chartInfoId, chartType int, calendar, startDate, endDate st
 	case 10: // 截面散点图
 		sectionScatterConf := extraConfig.(data_manage.SectionScatterReq)
 		xEdbIdValue, dataResp, err = GetSectionScatterChartData(mappingList, edbDataListMap, sectionScatterConf)
+	case utils.CHART_TYPE_SECTION_COMBINE: // 截面组合图
+		sectionConf := extraConfig.(models.ChartSectionAllExtraConf)
+		var chartInfo *models.ChartInfo
+		if chartInfoId > 0 {
+			chartInfo, err = models.GetChartInfoById(chartInfoId)
+			if err != nil {
+				errMsg = "获取图表信息失败"
+				return
+			}
+		}
+
+		xEdbIdValue, dataResp, err = GetChartSectionCombineData(chartInfo, mappingList, edbDataListMap, sectionConf)
 
 		// 这个数据没有必要返回给前端
 		for _, v := range edbList {
@@ -1494,11 +1681,23 @@ func RadarChartData(mappingList []*models.ChartEdbInfoMapping, edbDataListMap ma
 // GetChartEdbDataV2 获取图表的指标数据
 func GetChartEdbDataV2(chartInfoId, chartType int, calendar, startDate, endDate string, mappingList []*models.ChartEdbInfoMapping, extraConfigStr, seasonExtraConfig string, chartInfoData ChartInfoDataShow) (edbList []*models.ChartEdbInfoMapping, xEdbIdValue []int, yDataList []models.YData, dataResp interface{}, err error, errMsg string) {
 	edbList = make([]*models.ChartEdbInfoMapping, 0)
-	// 指标对应的所有数据
 	xEdbIdValue = make([]int, 0)
 	yDataList = make([]models.YData, 0)
+
 	var extraConfig interface{}
 	switch chartType {
+	case 6:
+		var tmpConfig models.ChartTimeCombineExtraConf
+		if extraConfigStr != `` {
+			err = json.Unmarshal([]byte(extraConfigStr), &tmpConfig)
+			if err != nil {
+				errMsg = "雷达图配置异常"
+				err = errors.New(errMsg)
+				return
+			}
+		}
+
+		extraConfig = tmpConfig
 	case 7: // 柱形图
 		var barConfig data_manage.BarChartInfoReq
 		if extraConfigStr == `` {
@@ -1526,6 +1725,7 @@ func GetChartEdbDataV2(chartInfoId, chartType int, calendar, startDate, endDate
 			err = errors.New(errMsg)
 			return
 		}
+
 		extraConfig = tmpExtraConfig
 	case utils.CHART_TYPE_RADAR:
 		var barConfig data_manage.RadarChartInfoReq
@@ -1541,6 +1741,159 @@ func GetChartEdbDataV2(chartInfoId, chartType int, calendar, startDate, endDate
 			return
 		}
 		extraConfig = barConfig
+	case utils.CHART_TYPE_SECTION_COMBINE:
+		// 预览和详情都走这个接口
+		var sectionExtraConfig models.ChartSectionAllExtraConf
+		if extraConfigStr == `` {
+			errMsg = "截面组合图未配置"
+			err = errors.New(errMsg)
+			return
+		}
+		if chartInfoId > 0 {
+			var sectionExtraConfigTmp models.ChartSectionExtraConf
+			err = json.Unmarshal([]byte(extraConfigStr), &sectionExtraConfigTmp)
+			if err != nil {
+				errMsg = "截面组合图配置异常"
+				err = errors.New(errMsg)
+				return
+			}
+			sectionExtraConfig.XDataList = sectionExtraConfigTmp.XDataList
+			sectionExtraConfig.BaseChartSeriesName = sectionExtraConfigTmp.BaseChartSeriesName
+			sectionExtraConfig.UnitList = sectionExtraConfigTmp.UnitList
+			sectionExtraConfig.DateConfList = sectionExtraConfigTmp.DateConfList
+			sectionExtraConfig.IsHeap = sectionExtraConfigTmp.IsHeap
+			sectionExtraConfig.SortType = sectionExtraConfigTmp.SortType
+			// 查询所有的seriesEdb
+			seriesEdbList, e := models.GetChartSeriesEdbByChartInfoId(chartInfoId)
+			if e != nil {
+				errMsg = "查询seriesEdb失败"
+				err = errors.New(errMsg + e.Error())
+				return
+			}
+			// todo 是否有必要返回单位信息
+			// 组装成map
+			seriesEdbMap := make(map[int][]*models.ChartSectionSeriesEdbConf)
+			for _, v := range seriesEdbList {
+				var dateConf *models.ChartSectionSeriesDateConfItem
+				if v.DateConf != "" {
+					err = json.Unmarshal([]byte(v.DateConf), &dateConf)
+					if err != nil {
+						errMsg = "截面组合图配置异常"
+						err = errors.New(errMsg + err.Error())
+						return
+					}
+				}
+				tmp := &models.ChartSectionSeriesEdbConf{
+					ChartSeriesEdbMappingId: v.ChartSeriesEdbMappingId,
+					ChartSeriesId:           v.ChartSeriesId,
+					//ChartInfoId:             v.ChartInfoId,
+					EdbInfoId:    v.EdbInfoId,
+					DateConf:     dateConf,
+					EdbName:      "",
+					EdbNameEn:    "",
+					Unit:         "",
+					UnitEn:       "",
+					DateConfName: v.DateConfName,
+					DateConfType: v.DateConfType,
+				}
+				seriesEdbMap[v.ChartSeriesId] = append(seriesEdbMap[v.ChartSeriesId], tmp)
+			}
+			//查询series
+			seriesListTmp, e := models.GetChartSeriesByChartInfoId(chartInfoId)
+			if e != nil {
+				errMsg = "查询series失败"
+				err = errors.New(errMsg + e.Error())
+				return
+			}
+			seriesList := make([]*models.ChartSectionSeriesItem, 0)
+			for _, v := range seriesListTmp {
+
+				tmpSeries := &models.ChartSectionSeriesItem{
+					ChartSeriesId: v.ChartSeriesId,
+					SeriesName:    v.SeriesName,
+					SeriesNameEn:  v.SeriesNameEn,
+					ChartStyle:    v.ChartStyle,
+					ChartColor:    v.ChartColor,
+					ChartWidth:    v.ChartWidth,
+					IsPoint:       v.IsPoint,
+					IsNumber:      v.IsNumber,
+					IsAxis:        v.IsAxis,
+					MaxData:       v.MaxData,
+					MinData:       v.MinData,
+					//IsOrder:         false,
+					EdbInfoList: nil,
+					DataList:    nil,
+				}
+				edbInfoList, ok := seriesEdbMap[v.ChartSeriesId]
+				if ok {
+					tmpSeries.EdbInfoList = edbInfoList
+				}
+				seriesList = append(seriesList, tmpSeries)
+			}
+			sectionExtraConfig.SeriesList = seriesList
+
+		} else {
+			err = json.Unmarshal([]byte(extraConfigStr), &sectionExtraConfig)
+			if err != nil {
+				errMsg = "截面组合图配置异常"
+				err = errors.New(errMsg)
+				return
+			}
+		}
+
+		//校验引用日期名称是否重复
+		dateNameMap := make(map[string]int)
+		dateNameEnMap := make(map[string]int)
+		for _, v := range sectionExtraConfig.DateConfList {
+			if _, ok := dateNameMap[v.DateConfName]; ok {
+				errMsg = "截面组合图引用日期名称设置重复"
+				err = errors.New(errMsg + v.DateConfName)
+				return
+			}
+			if _, ok := dateNameEnMap[v.DateConfNameEn]; ok {
+				errMsg = "截面组合图引用日期名称设置重复"
+				err = errors.New(errMsg + v.DateConfNameEn)
+				return
+			}
+			if v.DateConfName != "" {
+				dateNameMap[v.DateConfName] = 1
+			}
+			if v.DateConfNameEn != "" {
+				dateNameEnMap[v.DateConfNameEn] = 1
+			}
+
+		}
+
+		//检查系列名称是否重复
+		seriesNameMap := make(map[string]int)
+		seriesNameEnMap := make(map[string]int)
+		for _, v := range sectionExtraConfig.SeriesList {
+			if _, ok := seriesNameMap[v.SeriesName]; ok {
+				errMsg = "截面组合图系列名称设置重复"
+				err = errors.New(errMsg + v.SeriesName)
+				return
+			}
+			if _, ok := seriesNameEnMap[v.SeriesNameEn]; ok {
+				errMsg = "截面组合图系列名称设置重复"
+				err = errors.New(errMsg + v.SeriesNameEn)
+				return
+			}
+			if v.SeriesName != "" {
+				seriesNameMap[v.SeriesName] = 1
+			}
+			if v.SeriesNameEn != "" {
+				seriesNameEnMap[v.SeriesNameEn] = 1
+			}
+		}
+
+		// 检查基准系列是否设置
+		if sectionExtraConfig.BaseChartSeriesName == "" {
+			errMsg = "截面组合图基准系列名称未设置"
+			err = errors.New(errMsg)
+			return
+		}
+		//todo 如果是详情接口,应该要从其他表里查询配置
+		extraConfig = sectionExtraConfig
 	default:
 		xEdbIdValue = make([]int, 0)
 		yDataList = make([]models.YData, 0)
@@ -1554,6 +1907,15 @@ func GetChartEdbDataV2(chartInfoId, chartType int, calendar, startDate, endDate
 
 	// 特殊图形数据处理
 	switch chartType {
+	case 6: //时序组合图
+		//判断是否堆积
+		timeConf := extraConfig.(models.ChartTimeCombineExtraConf)
+		if extraConfigStr == "" { //历史数据,默认开启堆积
+			timeConf = models.ChartTimeCombineExtraConf{
+				IsHeap: 1,
+			}
+		}
+		dataResp = models.ChartTimeCombineDataResp{IsHeap: timeConf.IsHeap}
 	case 7: // 柱形图
 		barChartConf := extraConfig.(data_manage.BarChartInfoReq)
 		xEdbIdValue, yDataList, err = BarChartData(mappingList, edbDataListMap, barChartConf.DateList, barChartConf.Sort)
@@ -1572,6 +1934,18 @@ func GetChartEdbDataV2(chartInfoId, chartType int, calendar, startDate, endDate
 		sectionScatterConf := extraConfig.(data_manage.SectionScatterReq)
 		xEdbIdValue, dataResp, err = GetSectionScatterChartData(mappingList, edbDataListMap, sectionScatterConf)
 
+	case utils.CHART_TYPE_SECTION_COMBINE: // 截面组合图
+		sectionConf := extraConfig.(models.ChartSectionAllExtraConf)
+		var chartInfo *models.ChartInfo
+		if chartInfoId > 0 {
+			chartInfo, err = models.GetChartInfoById(chartInfoId)
+			if err != nil {
+				errMsg = "获取图表信息失败"
+				return
+			}
+		}
+		xEdbIdValue, dataResp, err = GetChartSectionCombineData(chartInfo, mappingList, edbDataListMap, sectionConf)
+
 		// 这个数据没有必要返回给前端
 		for _, v := range edbList {
 			v.DataList = nil
@@ -1580,7 +1954,6 @@ func GetChartEdbDataV2(chartInfoId, chartType int, calendar, startDate, endDate
 		radarConf := extraConfig.(data_manage.RadarChartInfoReq)
 		xEdbIdValue, dataResp, err = RadarChartData(mappingList, edbDataListMap, radarConf)
 	}
-
 	return
 }
 

+ 1 - 0
utils/constants.go

@@ -162,6 +162,7 @@ const (
 	CHART_TYPE_BAR             = 7  //柱形图
 	CHART_TYPE_SECTION_SCATTER = 10 //截面散点图样式
 	CHART_TYPE_RADAR           = 11 //雷达图
+	CHART_TYPE_SECTION_COMBINE = 14 //截面组合图
 )
 
 // 图表类型