Преглед изворни кода

Merge branch 'feature/eta1.9.6_chart_series'

hsun пре 7 месеци
родитељ
комит
13632d4fde

+ 158 - 0
controllers/data_manage/chart_info_section.go

@@ -0,0 +1,158 @@
+package data_manage
+
+import (
+	"encoding/json"
+	"eta/eta_mobile/models"
+	"eta/eta_mobile/models/data_manage"
+	"eta/eta_mobile/services/data"
+	"eta/eta_mobile/utils"
+	"strings"
+)
+
+// GetChartTypeList
+// @Title 获取所有图表类型
+// @Description 获取所有图表类型
+// @Success 200 {object} data_manage.AddChartInfoResp
+// @router /chart_info/type_list [get]
+func (this *ChartInfoController) GetChartTypeList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+
+	listTmp, err := data_manage.GetChartTypeList()
+	if err != nil {
+		br.Msg = "获取图表类型失败"
+		br.ErrMsg = "获取图表类型失败,Err:" + err.Error()
+		return
+	}
+	//遍历list,将id和name组成map
+	chartTypeMap := make(map[int][]data_manage.ChartType)
+	for _, v := range listTmp {
+		if v.ParentId > 0 {
+			chartTypeMap[v.ParentId] = append(chartTypeMap[v.ParentId], v)
+		}
+	}
+	list := make([]data_manage.ChartTypeList, 0)
+	for _, v := range listTmp {
+		if v.ParentId == 0 {
+			tmp := data_manage.ChartTypeList{
+				ChartTypeId:     v.ChartTypeId,
+				ChartTypeName:   v.ChartTypeName,
+				ChartTypeNameEn: v.ChartTypeNameEn,
+				ParentId:        v.ParentId,
+			}
+			child, ok := chartTypeMap[v.ChartTypeId]
+			if ok {
+				tmp.Child = child
+			}
+			list = append(list, tmp)
+		}
+	}
+
+	resp := data_manage.ChartTypeListResp{List: list}
+	br.Data = resp
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取图表类型成功"
+
+}
+
+// PreviewSectionCombineChartInfo
+// @Title 图表-获取预览的截面组合图数据
+// @Description 图表-获取预览的截面组合图数据
+// @Param	request	body data_manage.PreviewSectionCombineChartReq true "type json string"
+// @Success 200 {object} data_manage.ChartEdbInfoDetailResp
+// @router /chart_info/preview/section_combine [post]
+func (this *ChartInfoController) PreviewSectionCombineChartInfo() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	var req data_manage.PreviewSectionCombineChartReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	chartInfo := new(data_manage.ChartInfoView)
+
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+
+	chartType := utils.CHART_TYPE_SECTION_COMBINE
+	edbInfoIdArr, err, errMsg := data.CheckChartExtraConfig(chartType, req.ExtraConfig)
+	if err != nil {
+		br.Msg = errMsg
+		br.ErrMsg = "添加失败:" + err.Error()
+		return
+	}
+	chartInfo.ChartType = chartType
+	mappingList, err := data_manage.GetChartEdbMappingListByEdbInfoIdList(edbInfoIdArr)
+
+	// 获取图表中的指标数据
+	edbList, xEdbIdValue, yDataList, dataResp, err, errMsg := data.GetChartEdbData(0, chartType, "", "", "", mappingList, req.ExtraConfig, "")
+	if err != nil {
+		br.Msg = "获取失败"
+		if errMsg != `` {
+			br.Msg = errMsg
+		}
+		br.ErrMsg = "获取图表,指标信息失败,Err:" + err.Error()
+		return
+	}
+	warnEdbList := make([]string, 0)
+	for _, v := range edbList {
+		if v.IsNullData {
+			warnEdbList = append(warnEdbList, v.EdbName+"("+v.EdbCode+")")
+		}
+	}
+	if len(warnEdbList) > 0 {
+		chartInfo.WarnMsg = `图表引用指标异常,异常指标:` + strings.Join(warnEdbList, ",")
+	}
+
+	// 图表的指标来源
+	sourceNameList, sourceNameEnList := data.GetEdbSourceByEdbInfoIdList(edbList)
+	chartInfo.ChartSource = strings.Join(sourceNameList, ",")
+	chartInfo.ChartSourceEn = strings.Join(sourceNameEnList, ",")
+
+	//图表操作权限
+	chartInfo.IsEdit = data.CheckOpChartPermission(sysUser, chartInfo.SysUserId, true)
+	//判断是否需要展示英文标识
+	chartInfo.IsEnChart = data.CheckIsEnChart(chartInfo.ChartNameEn, edbList, utils.CHART_SOURCE_DEFAULT, chartType)
+	chartInfo.Button = data_manage.ChartViewButton{
+		IsEdit:    chartInfo.IsEdit,
+		IsEnChart: chartInfo.IsEnChart,
+		IsAdd:     chartInfo.IsAdd,
+		IsCopy:    true,
+		IsSetName: chartInfo.IsSetName,
+	}
+
+	resp := new(data_manage.ChartInfoDetailResp)
+	resp.ChartInfo = chartInfo
+	resp.EdbInfoList = edbList
+	resp.XEdbIdValue = xEdbIdValue
+	resp.YDataList = yDataList
+	resp.DataResp = dataResp
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}

+ 120 - 0
models/data_manage/chart_info.go

@@ -2615,3 +2615,123 @@ func getThsHfEdbDataListMinAndMaxByMongo(source, subSource, edbInfoId int, start
 	maxData = result.MaxValue
 	maxData = result.MaxValue
 	return
 	return
 }
 }
+
+// 截面组合图额外配置
+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不堆积)"`
+}

+ 305 - 0
models/data_manage/chart_series.go

@@ -0,0 +1,305 @@
+package data_manage
+
+import (
+	"encoding/json"
+	"eta/eta_mobile/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/data_manage/chart_series_edb_mapping.go

@@ -0,0 +1,29 @@
+package data_manage
+
+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
+}

+ 38 - 0
models/data_manage/chart_type.go

@@ -0,0 +1,38 @@
+package data_manage
+
+import (
+	"github.com/beego/beego/v2/client/orm"
+)
+
+type ChartType struct {
+	ChartTypeId     int    `orm:"column(chart_type_id);pk"`
+	ChartTypeName   string `description:"图表类型名称"`
+	ChartTypeNameEn string `description:"英文图表类型名称"`
+	ParentId        int    `description:"父级ID"`
+	Sort            int    `description:"排序"`
+	CreateTime      string `description:"创建时间"`
+}
+
+type ChartTypeList struct {
+	ChartTypeId     int
+	ChartTypeName   string `description:"图表类型名称"`
+	ChartTypeNameEn string `description:"英文图表类型名称"`
+	ParentId        int    `description:"父级ID"`
+	Child           []ChartType
+}
+
+type ChartTypeListResp struct {
+	List []ChartTypeList
+}
+
+func (c *ChartType) TableName() string {
+	return "chart_type"
+}
+
+// 查询所有图表类型
+func GetChartTypeList() (items []ChartType, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT * FROM chart_type order by sort asc`
+	_, err = o.Raw(sql).QueryRows(&items)
+	return
+}

+ 18 - 0
routers/commentsRouter.go

@@ -2014,6 +2014,15 @@ func init() {
             Filters: nil,
             Filters: nil,
             Params: nil})
             Params: nil})
 
 
+    beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage:ChartInfoController"] = append(beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage:ChartInfoController"],
+        beego.ControllerComments{
+            Method: "PreviewSectionCombineChartInfo",
+            Router: `/chart_info/preview/section_combine`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage:ChartInfoController"] = append(beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage:ChartInfoController"],
     beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage:ChartInfoController"] = append(beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage:ChartInfoController"],
         beego.ControllerComments{
         beego.ControllerComments{
             Method: "PreviewSectionScatterChartInfo",
             Method: "PreviewSectionScatterChartInfo",
@@ -2059,6 +2068,15 @@ func init() {
             Filters: nil,
             Filters: nil,
             Params: nil})
             Params: nil})
 
 
+    beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage:ChartInfoController"] = append(beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage:ChartInfoController"],
+        beego.ControllerComments{
+            Method: "GetChartTypeList",
+            Router: `/chart_info/type_list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage:ChartInfoController"] = append(beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage:ChartInfoController"],
     beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage:ChartInfoController"] = append(beego.GlobalControllerRouter["eta/eta_mobile/controllers/data_manage:ChartInfoController"],
         beego.ControllerComments{
         beego.ControllerComments{
             Method: "SaveAdjustEdbInfo",
             Method: "SaveAdjustEdbInfo",

+ 744 - 2
services/data/chart_extra_config.go

@@ -5,13 +5,16 @@ import (
 	"errors"
 	"errors"
 	"eta/eta_mobile/models/data_manage"
 	"eta/eta_mobile/models/data_manage"
 	"eta/eta_mobile/services/google"
 	"eta/eta_mobile/services/google"
+	"eta/eta_mobile/utils"
+	"fmt"
+	"sort"
 	"strconv"
 	"strconv"
 	"strings"
 	"strings"
+	"time"
 )
 )
 
 
-func HandleExtraConfig(chartType int, extraConfigStr string) (newExtraConfigStr string, err error, errMsg string) {
+func HandleExtraConfig(chartType int, extraConfigStr string) (newExtraConfigStr string, newAllExtraConfigStr string, err error, errMsg string) {
 	newExtraConfigStr = extraConfigStr
 	newExtraConfigStr = extraConfigStr
-
 	switch chartType {
 	switch chartType {
 	case 10: // 截面散点图
 	case 10: // 截面散点图
 		var tmpExtraConfig data_manage.SectionScatterReq
 		var tmpExtraConfig data_manage.SectionScatterReq
@@ -28,6 +31,48 @@ func HandleExtraConfig(chartType int, extraConfigStr string) (newExtraConfigStr
 		}
 		}
 
 
 		newExtraConfigStr, err, errMsg = handleSectionScatterChartData(tmpExtraConfig)
 		newExtraConfigStr, err, errMsg = handleSectionScatterChartData(tmpExtraConfig)
+	case utils.CHART_TYPE_SECTION_COMBINE:
+		//整理组合图的配置信息,将部分信息存入其他表
+		// 预览和详情都走这个接口
+		var sectionExtraConfig data_manage.ChartSectionAllExtraConf
+		if extraConfigStr == `` {
+			errMsg = "截面组合图未配置"
+			err = errors.New(errMsg)
+			return
+		}
+		err = json.Unmarshal([]byte(extraConfigStr), &sectionExtraConfig)
+		if err != nil {
+			errMsg = "截面组合图配置异常"
+			err = errors.New(errMsg)
+			return
+		}
+		newAllExtraConfig, e, msg := handleChartSectionCombineData(sectionExtraConfig)
+		if e != nil {
+			err = e
+			errMsg = msg
+			return
+		}
+		newAllExtraConfigByte, e := json.Marshal(newAllExtraConfig)
+		if e != nil {
+			err = e
+			return
+		}
+		newAllExtraConfigStr = string(newAllExtraConfigByte)
+
+		newExtraConfig := &data_manage.ChartSectionExtraConf{
+			DateConfList:        newAllExtraConfig.DateConfList,
+			IsHeap:              newAllExtraConfig.IsHeap,
+			XDataList:           newAllExtraConfig.XDataList,
+			UnitList:            newAllExtraConfig.UnitList,
+			BaseChartSeriesName: newAllExtraConfig.BaseChartSeriesName,
+			SortType:            newAllExtraConfig.SortType,
+		}
+		extraConfigByte, e := json.Marshal(newExtraConfig)
+		if e != nil {
+			err = e
+			return
+		}
+		newExtraConfigStr = string(extraConfigByte)
 	}
 	}
 	return
 	return
 }
 }
@@ -197,3 +242,700 @@ func GetEnNameMapByCnNameList(cnNameList []string) (contentEnMap map[string]stri
 	}
 	}
 	return
 	return
 }
 }
+
+// handleSectionScatterChartData 截面组合图的英文文案处理
+func handleChartSectionCombineData(extraConfig data_manage.ChartSectionAllExtraConf) (newExtraConfig data_manage.ChartSectionAllExtraConf, err error, errMsg string) {
+	translateNameList := make([]string, 0)
+	translateNameMap := make(map[string]bool, 0)
+	for _, v := range extraConfig.DateConfList {
+		if _, ok := translateNameMap[v.DateConfName]; !ok && v.DateConfNameEn == "" {
+			translateNameMap[v.DateConfName] = true
+			tmpName := strings.TrimSuffix(v.DateConfName, " ")
+			tmpName = strings.TrimPrefix(tmpName, " ")
+			translateNameList = append(translateNameList, tmpName)
+		}
+	}
+
+	if _, ok := translateNameMap[extraConfig.UnitList.LeftName]; !ok && extraConfig.UnitList.LeftNameEn == "" {
+		translateNameMap[extraConfig.UnitList.LeftName] = true
+		tmpName := strings.TrimSuffix(extraConfig.UnitList.LeftName, " ")
+		tmpName = strings.TrimPrefix(tmpName, " ")
+		translateNameList = append(translateNameList, tmpName)
+	}
+	if _, ok := translateNameMap[extraConfig.UnitList.RightName]; !ok && extraConfig.UnitList.RightNameEn == "" {
+		translateNameMap[extraConfig.UnitList.RightName] = true
+		tmpName := strings.TrimSuffix(extraConfig.UnitList.RightName, " ")
+		tmpName = strings.TrimPrefix(tmpName, " ")
+		translateNameList = append(translateNameList, tmpName)
+	}
+	if _, ok := translateNameMap[extraConfig.UnitList.RightTwoName]; !ok && extraConfig.UnitList.RightTwoNameEn == "" {
+		translateNameMap[extraConfig.UnitList.RightTwoName] = true
+		tmpName := strings.TrimSuffix(extraConfig.UnitList.RightTwoName, " ")
+		tmpName = strings.TrimPrefix(tmpName, " ")
+		translateNameList = append(translateNameList, tmpName)
+	}
+
+	for _, v := range extraConfig.XDataList {
+		if _, ok := translateNameMap[v.Name]; !ok && v.NameEn == "" {
+			translateNameMap[v.Name] = true
+			tmpName := strings.TrimSuffix(v.Name, " ")
+			tmpName = strings.TrimPrefix(tmpName, " ")
+			translateNameList = append(translateNameList, tmpName)
+		}
+	}
+	for _, v := range extraConfig.SeriesList {
+		if v.SeriesNameEn == `` {
+			if _, ok := translateNameMap[v.SeriesName]; !ok {
+				translateNameMap[v.SeriesName] = true
+				tmpName := strings.TrimSuffix(v.SeriesName, " ")
+				tmpName = strings.TrimPrefix(tmpName, " ")
+				translateNameList = append(translateNameList, tmpName)
+			}
+		}
+	}
+
+	// 获取英文名称map
+	enNameMap, _, _ := GetEnNameMapByCnNameList(translateNameList)
+
+	for k, seriesItem := range extraConfig.SeriesList {
+		if len(seriesItem.EdbInfoList) <= 0 {
+			errMsg = "指标不能为空"
+			err = errors.New(errMsg)
+			return
+		}
+		if seriesItem.SeriesNameEn == `` { //系列英文名称
+			if tmpNameEn, ok := enNameMap[seriesItem.SeriesName]; ok {
+				seriesItem.SeriesNameEn = tmpNameEn
+			}
+		}
+		extraConfig.SeriesList[k] = seriesItem
+	}
+
+	for k, v := range extraConfig.XDataList {
+		if tmpNameEn, ok := enNameMap[v.Name]; ok && v.NameEn == "" {
+			extraConfig.XDataList[k].NameEn = tmpNameEn
+		}
+	}
+
+	if tmpNameEn, ok := enNameMap[extraConfig.UnitList.LeftName]; ok && extraConfig.UnitList.LeftNameEn == "" {
+		extraConfig.UnitList.LeftName = tmpNameEn
+	}
+	if tmpNameEn, ok := enNameMap[extraConfig.UnitList.RightName]; ok && extraConfig.UnitList.RightNameEn == "" {
+		extraConfig.UnitList.RightName = tmpNameEn
+	}
+	if tmpNameEn, ok := enNameMap[extraConfig.UnitList.RightTwoName]; ok && extraConfig.UnitList.RightTwoNameEn == "" {
+		extraConfig.UnitList.RightTwoName = tmpNameEn
+	}
+	for k, v := range extraConfig.DateConfList {
+		if tmpNameEn, ok := enNameMap[v.DateConfName]; ok && v.DateConfNameEn == "" {
+			extraConfig.DateConfList[k].DateConfNameEn = tmpNameEn
+		}
+	}
+
+	newExtraConfig = extraConfig
+	return
+}
+
+// GetChartSectionCombineData 截面组合图的数据处理
+func GetChartSectionCombineData(chartInfo *data_manage.ChartInfo, mappingList []*data_manage.ChartEdbInfoMapping, edbDataListMap map[int][]*data_manage.EdbDataList, extraConfig data_manage.ChartSectionAllExtraConf) (edbIdList []int, dataListResp data_manage.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]*data_manage.ChartEdbInfoMapping)
+	for _, v := range mappingList {
+		edbIdList = append(edbIdList, v.EdbInfoId)
+		edbMappingMap[v.EdbInfoId] = v
+	}
+	// 确定好截面散点图返回的数据格式
+	// 获取所有的引用日期设置
+	dateConfListMap := make(map[string]*data_manage.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(data_manage.ChartSectionSeriesItem) //y轴的系列
+	var firstUnit, leftUnit, rightUnit, right2Unit *data_manage.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 = &data_manage.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([]*data_manage.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([]data_manage.XData, 0)
+	for index, item := range baseSeries.EdbInfoList {
+		if index == 0 {
+			firstUnit = &data_manage.XData{
+				Name:   item.Unit,
+				NameEn: item.UnitEn,
+			}
+		}
+		tmp := data_manage.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(data_manage.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 := data_manage.GetEdbInfoByIdList(dateConfEdbIds)
+		if e != nil {
+			err = fmt.Errorf("查询引用日期里的指标信息失败,错误信息:%s", e.Error())
+			return
+		}
+		dateConfEdbMap := make(map[int]*data_manage.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 []*data_manage.EdbDataList, dateChange []*data_manage.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 []*data_manage.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 []*data_manage.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([]data_manage.ChartSectionSeriesValSort, length)
+	for i, value := range baseDataList {
+		if i < length {
+			baseDataSortList[i] = data_manage.ChartSectionSeriesValSort{Index: i, Value: value}
+		}
+	}
+	if asc == 1 {
+		// 使用sort.Sort进行排序
+		sort.Sort(data_manage.ChartSectionSeriesValSortAsc(baseDataSortList))
+	} else {
+		sort.Sort(data_manage.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
+}

+ 493 - 5
services/data/chart_info.go

@@ -301,6 +301,18 @@ func GetChartEdbData(chartInfoId, chartType int, calendar, startDate, endDate st
 
 
 	var extraConfig interface{}
 	var extraConfig interface{}
 	switch chartType {
 	switch chartType {
+	case 6:
+		var tmpConfig data_manage.ChartTimeCombineExtraConf
+		if extraConfigStr != `` {
+			err = json.Unmarshal([]byte(extraConfigStr), &tmpConfig)
+			if err != nil {
+				errMsg = "雷达图配置异常"
+				err = errors.New(errMsg)
+				return
+			}
+		}
+
+		extraConfig = tmpConfig
 	case 7: // 柱形图
 	case 7: // 柱形图
 		var barConfig data_manage.BarChartInfoReq
 		var barConfig data_manage.BarChartInfoReq
 		if extraConfigStr == `` {
 		if extraConfigStr == `` {
@@ -344,6 +356,159 @@ func GetChartEdbData(chartInfoId, chartType int, calendar, startDate, endDate st
 			return
 			return
 		}
 		}
 		extraConfig = barConfig
 		extraConfig = barConfig
+	case utils.CHART_TYPE_SECTION_COMBINE:
+		// 预览和详情都走这个接口
+		var sectionExtraConfig data_manage.ChartSectionAllExtraConf
+		if extraConfigStr == `` {
+			errMsg = "截面组合图未配置"
+			err = errors.New(errMsg)
+			return
+		}
+		if chartInfoId > 0 {
+			var sectionExtraConfigTmp data_manage.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 := data_manage.GetChartSeriesEdbByChartInfoId(chartInfoId)
+			if e != nil {
+				errMsg = "查询seriesEdb失败"
+				err = errors.New(errMsg + e.Error())
+				return
+			}
+			// todo 是否有必要返回单位信息
+			// 组装成map
+			seriesEdbMap := make(map[int][]*data_manage.ChartSectionSeriesEdbConf)
+			for _, v := range seriesEdbList {
+				var dateConf *data_manage.ChartSectionSeriesDateConfItem
+				if v.DateConf != "" {
+					err = json.Unmarshal([]byte(v.DateConf), &dateConf)
+					if err != nil {
+						errMsg = "截面组合图配置异常"
+						err = errors.New(errMsg + err.Error())
+						return
+					}
+				}
+				tmp := &data_manage.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 := data_manage.GetChartSeriesByChartInfoId(chartInfoId)
+			if e != nil {
+				errMsg = "查询series失败"
+				err = errors.New(errMsg + e.Error())
+				return
+			}
+			seriesList := make([]*data_manage.ChartSectionSeriesItem, 0)
+			for _, v := range seriesListTmp {
+
+				tmpSeries := &data_manage.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:
 	default:
 		xEdbIdValue = make([]int, 0)
 		xEdbIdValue = make([]int, 0)
 		yDataList = make([]data_manage.YData, 0)
 		yDataList = make([]data_manage.YData, 0)
@@ -370,6 +535,15 @@ func GetChartEdbData(chartInfoId, chartType int, calendar, startDate, endDate st
 			// 兼容无配置的老图
 			// 兼容无配置的老图
 			dataResp = new(data_manage.SeasonChartResp)
 			dataResp = new(data_manage.SeasonChartResp)
 		}
 		}
+	case 6: //时序组合图
+		//判断是否堆积
+		timeConf := extraConfig.(data_manage.ChartTimeCombineExtraConf)
+		if extraConfigStr == "" { //历史数据,默认开启堆积
+			timeConf = data_manage.ChartTimeCombineExtraConf{
+				IsHeap: 1,
+			}
+		}
+		dataResp = data_manage.ChartTimeCombineDataResp{IsHeap: timeConf.IsHeap}
 	case 7: // 柱形图
 	case 7: // 柱形图
 		barChartConf := extraConfig.(data_manage.BarChartInfoReq)
 		barChartConf := extraConfig.(data_manage.BarChartInfoReq)
 		xEdbIdValue, yDataList, err = BarChartData(mappingList, edbDataListMap, barChartConf.DateList, barChartConf.Sort)
 		xEdbIdValue, yDataList, err = BarChartData(mappingList, edbDataListMap, barChartConf.DateList, barChartConf.Sort)
@@ -406,6 +580,23 @@ func GetChartEdbData(chartInfoId, chartType int, calendar, startDate, endDate st
 			return
 			return
 		}
 		}
 
 
+		// 这个数据没有必要返回给前端
+		for _, v := range edbList {
+			v.DataList = nil
+		}
+	case utils.CHART_TYPE_SECTION_COMBINE: // 截面组合图
+		sectionConf := extraConfig.(data_manage.ChartSectionAllExtraConf)
+		var chartInfo *data_manage.ChartInfo
+		if chartInfoId > 0 {
+			chartInfo, err = data_manage.GetChartInfoById(chartInfoId)
+			if err != nil {
+				errMsg = "获取图表信息失败"
+				return
+			}
+		}
+
+		xEdbIdValue, dataResp, err = GetChartSectionCombineData(chartInfo, mappingList, edbDataListMap, sectionConf)
+
 		// 这个数据没有必要返回给前端
 		// 这个数据没有必要返回给前端
 		for _, v := range edbList {
 		for _, v := range edbList {
 			v.DataList = nil
 			v.DataList = nil
@@ -1631,6 +1822,96 @@ func CheckChartExtraConfig(chartType int, extraConfigStr string) (edbIdList []in
 			err = errors.New(errMsg)
 			err = errors.New(errMsg)
 			return
 			return
 		}
 		}
+	case utils.CHART_TYPE_SECTION_COMBINE:
+		var extraConfig data_manage.ChartSectionAllExtraConf
+		if extraConfigStr == `` {
+			errMsg = "截面组合图未配置"
+			err = errors.New(errMsg)
+			return
+		}
+		err = json.Unmarshal([]byte(extraConfigStr), &extraConfig)
+		if err != nil {
+			errMsg = "截面组合图配置异常"
+			err = errors.New(errMsg + err.Error())
+			return
+		}
+		//校验引用日期名称是否重复
+		dateNameMap := make(map[string]int)
+		dateNameEnMap := make(map[string]int)
+		for _, v := range extraConfig.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 extraConfig.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 extraConfig.BaseChartSeriesName == "" {
+			errMsg = "截面组合图基准系列名称未设置"
+			err = errors.New(errMsg)
+			return
+		}
+		//todo 如果是详情接口,应该要从其他表里查询配置
+
+		// 遍历指标列表获取指标id
+		edbIdMap := make(map[int]int)
+		hasUsed := make(map[string]struct{})
+		for _, v := range extraConfig.SeriesList {
+			for _, item := range v.EdbInfoList {
+				if item.DateConfName != "" && item.DateConfType == 1 {
+					hasUsed[item.DateConfName] = struct{}{}
+				}
+				if _, ok := edbIdMap[item.EdbInfoId]; !ok {
+					edbIdMap[item.EdbInfoId] = item.EdbInfoId
+					edbIdList = append(edbIdList, item.EdbInfoId)
+				}
+			}
+		}
+		// todo 遍历引用日期获取引用日期里的指标ID, 如果引用日期里的指标没有被引用,是否加入映射
+		for _, v := range extraConfig.DateConfList {
+			if _, ok := hasUsed[v.DateConfName]; !ok {
+				continue
+			}
+			if _, ok := edbIdMap[v.EdbInfoId]; !ok && v.EdbInfoId > 0 {
+				edbIdMap[v.EdbInfoId] = v.EdbInfoId
+				edbIdList = append(edbIdList, v.EdbInfoId)
+			}
+		}
 	}
 	}
 	return
 	return
 }
 }
@@ -2136,7 +2417,9 @@ func AddChartInfo(req data_manage.AddChartInfoReq, sysUserId int, sysUserRealNam
 	}
 	}
 
 
 	// 图表额外配置
 	// 图表额外配置
-	extraConfig, err, errMsg = HandleExtraConfig(chartType, extraConfig)
+	// 图表额外配置
+	var allExtraConfig string
+	extraConfig, allExtraConfig, err, errMsg = HandleExtraConfig(chartType, extraConfig)
 	if err != nil {
 	if err != nil {
 		if errMsg == `` {
 		if errMsg == `` {
 			errMsg = "指标异常!"
 			errMsg = "指标异常!"
@@ -2319,6 +2602,15 @@ func AddChartInfo(req data_manage.AddChartInfoReq, sysUserId int, sysUserRealNam
 		return
 		return
 	}
 	}
 
 
+	if chartType == utils.CHART_TYPE_SECTION_COMBINE {
+		err = data_manage.AddChartSeriesAndEdbMapping(allExtraConfig, int(newId))
+		if err != nil {
+			errMsg = `保存失败`
+			err = errors.New("保存失败,Err:" + err.Error())
+			return
+		}
+	}
+
 	//添加es数据
 	//添加es数据
 	go EsAddOrEditChartInfo(chartInfo.ChartInfoId)
 	go EsAddOrEditChartInfo(chartInfo.ChartInfoId)
 
 
@@ -2520,7 +2812,7 @@ func EditChartInfo(req data_manage.EditChartInfoReq, sysUser *system.Admin, lang
 	}
 	}
 
 
 	// 图表额外配置
 	// 图表额外配置
-	extraConfig, err, errMsg := HandleExtraConfig(req.ChartType, req.ExtraConfig)
+	extraConfig, allExtraConfig, err, errMsg := HandleExtraConfig(req.ChartType, req.ExtraConfig)
 	if err != nil {
 	if err != nil {
 		if errMsg == `` {
 		if errMsg == `` {
 			errMsg = "指标异常!"
 			errMsg = "指标异常!"
@@ -2670,6 +2962,14 @@ func EditChartInfo(req data_manage.EditChartInfoReq, sysUser *system.Admin, lang
 	resp.UniqueCode = chartItem.UniqueCode
 	resp.UniqueCode = chartItem.UniqueCode
 	resp.ChartType = req.ChartType
 	resp.ChartType = req.ChartType
 
 
+	if chartItem.ChartType == utils.CHART_TYPE_SECTION_COMBINE {
+		err = data_manage.EditChartSeriesAndEdbMapping(allExtraConfig, chartItem.ChartInfoId)
+		if err != nil {
+			errMsg = "保存失败"
+			err = errors.New("保存失败,Err:" + err.Error())
+			return
+		}
+	}
 	//添加es数据
 	//添加es数据
 	go EsAddOrEditChartInfo(chartItem.ChartInfoId)
 	go EsAddOrEditChartInfo(chartItem.ChartInfoId)
 	//修改my eta es数据
 	//修改my eta es数据
@@ -3215,6 +3515,18 @@ func GetChartEdbDataV2(chartInfoId, chartType int, calendar, startDate, endDate
 
 
 	var extraConfig interface{}
 	var extraConfig interface{}
 	switch chartType {
 	switch chartType {
+	case 6:
+		var tmpConfig data_manage.ChartTimeCombineExtraConf
+		if extraConfigStr != `` {
+			err = json.Unmarshal([]byte(extraConfigStr), &tmpConfig)
+			if err != nil {
+				errMsg = "雷达图配置异常"
+				err = errors.New(errMsg)
+				return
+			}
+		}
+
+		extraConfig = tmpConfig
 	case 7: // 柱形图
 	case 7: // 柱形图
 		var barConfig data_manage.BarChartInfoReq
 		var barConfig data_manage.BarChartInfoReq
 		if extraConfigStr == `` {
 		if extraConfigStr == `` {
@@ -3258,6 +3570,159 @@ func GetChartEdbDataV2(chartInfoId, chartType int, calendar, startDate, endDate
 			return
 			return
 		}
 		}
 		extraConfig = barConfig
 		extraConfig = barConfig
+	case utils.CHART_TYPE_SECTION_COMBINE:
+		// 预览和详情都走这个接口
+		var sectionExtraConfig data_manage.ChartSectionAllExtraConf
+		if extraConfigStr == `` {
+			errMsg = "截面组合图未配置"
+			err = errors.New(errMsg)
+			return
+		}
+		if chartInfoId > 0 {
+			var sectionExtraConfigTmp data_manage.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 := data_manage.GetChartSeriesEdbByChartInfoId(chartInfoId)
+			if e != nil {
+				errMsg = "查询seriesEdb失败"
+				err = errors.New(errMsg + e.Error())
+				return
+			}
+			// todo 是否有必要返回单位信息
+			// 组装成map
+			seriesEdbMap := make(map[int][]*data_manage.ChartSectionSeriesEdbConf)
+			for _, v := range seriesEdbList {
+				var dateConf *data_manage.ChartSectionSeriesDateConfItem
+				if v.DateConf != "" {
+					err = json.Unmarshal([]byte(v.DateConf), &dateConf)
+					if err != nil {
+						errMsg = "截面组合图配置异常"
+						err = errors.New(errMsg + err.Error())
+						return
+					}
+				}
+				tmp := &data_manage.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 := data_manage.GetChartSeriesByChartInfoId(chartInfoId)
+			if e != nil {
+				errMsg = "查询series失败"
+				err = errors.New(errMsg + e.Error())
+				return
+			}
+			seriesList := make([]*data_manage.ChartSectionSeriesItem, 0)
+			for _, v := range seriesListTmp {
+
+				tmpSeries := &data_manage.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:
 	default:
 		xEdbIdValue = make([]int, 0)
 		xEdbIdValue = make([]int, 0)
 		yDataList = make([]data_manage.YData, 0)
 		yDataList = make([]data_manage.YData, 0)
@@ -3284,6 +3749,15 @@ func GetChartEdbDataV2(chartInfoId, chartType int, calendar, startDate, endDate
 			// 兼容无配置的老图
 			// 兼容无配置的老图
 			dataResp = new(data_manage.SeasonChartResp)
 			dataResp = new(data_manage.SeasonChartResp)
 		}
 		}
+	case 6: //时序组合图
+		//判断是否堆积
+		timeConf := extraConfig.(data_manage.ChartTimeCombineExtraConf)
+		if extraConfigStr == "" { //历史数据,默认开启堆积
+			timeConf = data_manage.ChartTimeCombineExtraConf{
+				IsHeap: 1,
+			}
+		}
+		dataResp = data_manage.ChartTimeCombineDataResp{IsHeap: timeConf.IsHeap}
 	case 7: // 柱形图
 	case 7: // 柱形图
 		barChartConf := extraConfig.(data_manage.BarChartInfoReq)
 		barChartConf := extraConfig.(data_manage.BarChartInfoReq)
 		xEdbIdValue, yDataList, err = BarChartData(mappingList, edbDataListMap, barChartConf.DateList, barChartConf.Sort)
 		xEdbIdValue, yDataList, err = BarChartData(mappingList, edbDataListMap, barChartConf.DateList, barChartConf.Sort)
@@ -3320,6 +3794,22 @@ func GetChartEdbDataV2(chartInfoId, chartType int, calendar, startDate, endDate
 			return
 			return
 		}
 		}
 
 
+		// 这个数据没有必要返回给前端
+		for _, v := range edbList {
+			v.DataList = nil
+		}
+	case utils.CHART_TYPE_SECTION_COMBINE: // 截面组合图
+		sectionConf := extraConfig.(data_manage.ChartSectionAllExtraConf)
+		var chartInfo *data_manage.ChartInfo
+		if chartInfoId > 0 {
+			chartInfo, err = data_manage.GetChartInfoById(chartInfoId)
+			if err != nil {
+				errMsg = "获取图表信息失败"
+				return
+			}
+		}
+		xEdbIdValue, dataResp, err = GetChartSectionCombineData(chartInfo, mappingList, edbDataListMap, sectionConf)
+
 		// 这个数据没有必要返回给前端
 		// 这个数据没有必要返回给前端
 		for _, v := range edbList {
 		for _, v := range edbList {
 			v.DataList = nil
 			v.DataList = nil
@@ -3331,7 +3821,6 @@ func GetChartEdbDataV2(chartInfoId, chartType int, calendar, startDate, endDate
 	return
 	return
 }
 }
 
 
-
 // SeasonChartData 季节性图的数据处理
 // SeasonChartData 季节性图的数据处理
 func SeasonChartData(dataList []*data_manage.ChartEdbInfoMapping, seasonExtraConfig string) (dataResp data_manage.SeasonChartResp, err error) {
 func SeasonChartData(dataList []*data_manage.ChartEdbInfoMapping, seasonExtraConfig string) (dataResp data_manage.SeasonChartResp, err error) {
 	var seasonConfig data_manage.SeasonExtraItem
 	var seasonConfig data_manage.SeasonExtraItem
@@ -3897,7 +4386,6 @@ func HandleDateChange(date string, edbDateConf data_manage.EdbDateChangeConf) (n
 	return
 	return
 }
 }
 
 
-
 // handleSystemAppointDateT
 // handleSystemAppointDateT
 // @Description: 处理系统日期相关的指定频率(所在周/旬/月/季/半年/年的最后/最早一天)
 // @Description: 处理系统日期相关的指定频率(所在周/旬/月/季/半年/年的最后/最早一天)
 // @author: Roc
 // @author: Roc
@@ -4025,4 +4513,4 @@ func handleSystemAppointDateT2(currDate time.Time, appointDay, frequency string)
 	}
 	}
 
 
 	return
 	return
-}
+}

+ 1 - 0
utils/constants.go

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