소스 검색

feat:新增柱方图

Roc 2 년 전
부모
커밋
196da4f087

+ 37 - 3
controller/chart/chart_info.go

@@ -2,10 +2,12 @@ package chart
 
 import (
 	"context"
+	"encoding/json"
 	"fmt"
 	"github.com/gin-gonic/gin"
 	"hongze/hongze_yb/controller/response"
 	"hongze/hongze_yb/global"
+	"hongze/hongze_yb/models/request"
 	"hongze/hongze_yb/models/response/chart_info"
 	chartEdbMappingModel "hongze/hongze_yb/models/tables/chart_edb_mapping"
 	chartInfoModel "hongze/hongze_yb/models/tables/chart_info"
@@ -173,10 +175,39 @@ func GetChartInfoDetail(c *gin.Context) {
 		}
 	}
 
-	fmt.Println("start_date:", startDate)
-	fmt.Println("end_date:", endDate)
+	//fmt.Println("start_date:", startDate)
+	//fmt.Println("end_date:", endDate)
+
+	barChartInfoDateList := make([]request.BarChartInfoDateReq, 0)
+	barChartInfoSort := request.BarChartInfoSortReq{}
+	// 柱方图的一些配置
+	if chartInfo != nil && chartInfo.ChartType == 7 {
+		if chartInfo.BarConfig == `` {
+			response.FailMsg("柱方图未配置", "柱方图未配置", c)
+			return
+		}
+
+		var barConfig request.BarChartInfoReq
+		err := json.Unmarshal([]byte(chartInfo.BarConfig), &barConfig)
+		if err != nil {
+			response.FailMsg("柱方图配置异常", "柱方图配置异常", c)
+			return
+		}
+
+		barChartInfoDateList = barConfig.DateList
+		barChartInfoSort = barConfig.Sort
+
+		// 指标别名
+		for _, v := range mappingList {
+			for _, confEdb := range barConfig.EdbInfoIdList {
+				if v.EdbInfoId == confEdb.EdbInfoId {
+					v.EdbAliasName = confEdb.Name
+				}
+			}
+		}
+	}
 	// 获取图表中的指标数据
-	edbList, sourceArr, err := chart.GetChartEdbData(chartInfoId, chartType, calendar, startDate, endDate, mappingList)
+	edbList, xEdbIdValue, yDataList, sourceArr, err := chart.GetChartEdbData(chartInfoId, chartType, calendar, startDate, endDate, mappingList, barChartInfoDateList, barChartInfoSort)
 	if err != nil {
 		response.FailMsg("获取失败", "获取图表,指标信息失败, Err:"+err.Error(), c)
 		return
@@ -197,6 +228,9 @@ func GetChartInfoDetail(c *gin.Context) {
 	resp := new(chart_info.ChartInfoDetailResp)
 	resp.ChartInfo = chartInfo
 	resp.EdbInfoList = edbList
+	resp.XEdbIdValue = xEdbIdValue
+	resp.YDataList = yDataList
+
 	response.OkData("获取成功", resp, c)
 }
 

+ 28 - 0
models/request/chart.go

@@ -0,0 +1,28 @@
+package request
+
+// BarChartInfoReq 柱方图预览请求数据
+type BarChartInfoReq struct {
+	EdbInfoIdList []BarChartInfoEdbItemReq `description:"指标信息"`
+	DateList      []BarChartInfoDateReq    `description:"日期配置"`
+	Sort          BarChartInfoSortReq      `description:"排序"`
+}
+
+// BarChartInfoEdbItemReq 柱方图预览请求数据(指标相关)
+type BarChartInfoEdbItemReq struct {
+	EdbInfoId int    `description:"指标ID"`
+	Name      string `description:"别名"`
+}
+
+// BarChartInfoDateReq 柱方图预览请求数据(日期相关)
+type BarChartInfoDateReq struct {
+	Type  int    `description:"配置类型"`
+	Date  string `description:"固定日期"`
+	Value int    `description:"N天的值"`
+	Color string `description:"颜色"`
+}
+
+// BarChartInfoSortReq 柱方图预览请求数据(排序相关)
+type BarChartInfoSortReq struct {
+	Sort      int `description:"排序类型,0:默认,1:升序,2:降序"`
+	DateIndex int `description:"日期数据的下标,从0开始"`
+}

+ 10 - 1
models/response/chart_info/chart_info.go

@@ -8,4 +8,13 @@ import (
 type ChartInfoDetailResp struct {
 	ChartInfo   *chart_info.ChartInfoView
 	EdbInfoList []*chart_edb_mapping.ChartEdbInfoMappingList
-}
+	XEdbIdValue []int   `description:"柱方图的x轴数据,指标id"`
+	YDataList   []YData `description:"柱方图的y轴数据"`
+}
+
+// YData 柱方图的y轴数据
+type YData struct {
+	Date  string    `description:"数据日期"`
+	Color string    `description:"数据颜色"`
+	Value []float64 `description:"每个指标的值"`
+}

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

@@ -11,6 +11,7 @@ type ChartEdbInfoMapping struct {
 	Source            int       `description:"来源id"`
 	EdbCode           string    `description:"指标编码"`
 	EdbName           string    `description:"指标名称"`
+	EdbAliasName      string    `description:"指标名称(别名)"`
 	EdbType           int       `description:"指标类型:1:基础指标,2:计算指标"`
 	Frequency         string    `description:"频率"`
 	Unit              string    `description:"单位"`

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

@@ -35,6 +35,7 @@ type ChartInfoView struct {
 	RightMin          string `description:"图表右侧最小值"`
 	RightMax          string `description:"图表右侧最大值"`
 	ChartSource       string `description:"图表来源str"`
+	BarConfig         string `description:"柱方图的配置,json数据" json:"-"`
 	//ChartClassify     []*chart_classify.ChartClassifyView
 }
 

+ 210 - 1
services/chart/chart_info.go

@@ -4,6 +4,8 @@ import (
 	"errors"
 	"fmt"
 	"hongze/hongze_yb/global"
+	"hongze/hongze_yb/models/request"
+	"hongze/hongze_yb/models/response/chart_info"
 	chartEdbMappingModel "hongze/hongze_yb/models/tables/chart_edb_mapping"
 	chartInfoModel "hongze/hongze_yb/models/tables/chart_info"
 	company2 "hongze/hongze_yb/models/tables/company"
@@ -400,8 +402,10 @@ func RefreshChart(chartInfoId int) (err error) {
 }
 
 // GetChartEdbData 获取图表的指标数据
-func GetChartEdbData(chartInfoId, chartType int, calendar, startDate, endDate string, mappingList []*chartEdbMappingModel.ChartEdbInfoMapping) (edbList []*chartEdbMappingModel.ChartEdbInfoMappingList, sourceArr []string, err error) {
+func GetChartEdbData(chartInfoId, chartType int, calendar, startDate, endDate string, mappingList []*chartEdbMappingModel.ChartEdbInfoMapping, barChartInfoDateList []request.BarChartInfoDateReq, barChartInfoSort request.BarChartInfoSortReq) (edbList []*chartEdbMappingModel.ChartEdbInfoMappingList, xEdbIdValue []int, yDataList []chart_info.YData, sourceArr []string, err error) {
 	edbList = make([]*chartEdbMappingModel.ChartEdbInfoMappingList, 0)
+	// 指标对应的所有数据
+	edbDataListMap := make(map[int][]*edbDataModel.EdbDataList)
 	sourceArr = make([]string, 0)
 
 	for _, v := range mappingList {
@@ -506,6 +510,7 @@ func GetChartEdbData(chartInfoId, chartType int, calendar, startDate, endDate st
 		}
 		dataList := make([]*edbDataModel.EdbDataList, 0)
 		//fmt.Println("chart:", v.Source, v.EdbInfoId, startDateReal, endDate, ";EdbInfoCategoryType:", v.EdbInfoCategoryType)
+		edbDataListMap[v.EdbInfoId] = dataList
 
 		//var newEdbInfo *edbInfoModel.EdbInfo
 		switch v.EdbInfoCategoryType {
@@ -639,11 +644,215 @@ func GetChartEdbData(chartInfoId, chartType int, calendar, startDate, endDate st
 				}
 				item.DataList = quarterDataList
 			}
+		} else if chartType == 7 { //柱方图
+			//item.DataList = dataList
 		} else {
 			item.DataList = dataList
 		}
 		edbList = append(edbList, item)
 	}
+
+	// 柱方图
+	if chartType == 7 {
+		xEdbIdValue, yDataList, err = BarChartData(mappingList, edbDataListMap, barChartInfoDateList, barChartInfoSort)
+	} else {
+		xEdbIdValue = make([]int, 0)
+		yDataList = make([]chart_info.YData, 0)
+	}
+
+	return
+}
+
+// BarChartData 柱方图的数据处理
+func BarChartData(mappingList []*chartEdbMappingModel.ChartEdbInfoMapping, edbDataListMap map[int][]*edbDataModel.EdbDataList, barChartInfoDateList []request.BarChartInfoDateReq, barChartInfoSort request.BarChartInfoSortReq) (edbIdList []int, yDataList []chart_info.YData, err error) {
+	// 指标数据数组(10086:{"2022-12-02":100.01,"2022-12-01":102.3})
+	edbDataMap := make(map[int]map[string]float64)
+	for edbInfoId, edbDataList := range edbDataListMap {
+		edbDateData := make(map[string]float64)
+		for _, edbData := range edbDataList {
+			edbDateData[edbData.DataTime] = edbData.Value
+		}
+		edbDataMap[edbInfoId] = edbDateData
+	}
+
+	// edbIdList 指标展示顺序;x轴的指标顺序
+	edbIdList = make([]int, 0)
+	//Sort int    `description:"排序类型,0:默认,1:升序,2:降序"`
+	dateData := make(map[int]float64)
+	if barChartInfoSort.Sort == 0 {
+		for _, v := range mappingList {
+			edbIdList = append(edbIdList, v.EdbInfoId)
+		}
+	} else {
+		lenBarChartInfoDateList := len(barChartInfoDateList)
+		if barChartInfoSort.DateIndex >= lenBarChartInfoDateList {
+			err = errors.New("排序日期异常")
+			return
+		}
+
+		notDataEdbIdList := make([]int, 0) //没有数据的指标id
+		// 日期配置
+		barChartInfoDate := barChartInfoDateList[barChartInfoSort.DateIndex]
+		for edbInfoId, dataList := range edbDataListMap {
+			findDate := barChartInfoDate.Date
+			switch barChartInfoDate.Type {
+			case 1: //最新值
+				findDate = dataList[len(dataList)-1].DataTime
+			case 2: //近期几天
+				findDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, dataList[len(dataList)-1].DataTime, time.Local)
+				if tmpErr != nil {
+					err = tmpErr
+					return
+				}
+				findDateTime = findDateTime.AddDate(0, 0, -barChartInfoDate.Value)
+
+				lenData := len(dataList) - 1
+
+				for i := lenData; i >= 0; i-- {
+					currDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, dataList[i].DataTime, time.Local)
+					if tmpErr != nil {
+						err = tmpErr
+						return
+					}
+					if utils.GetTimeSubDay(currDateTime, findDateTime) >= 5 {
+						findDate = dataList[i].DataTime
+						break
+					}
+				}
+			case 3: // 固定日期
+				//最早的日期
+				minDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, dataList[0].DataTime, time.Local)
+				if tmpErr != nil {
+					err = tmpErr
+					return
+				}
+				//寻找固定日期的数据
+				findDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, barChartInfoDate.Date, time.Local)
+				if tmpErr != nil {
+					err = tmpErr
+					return
+				}
+				for tmpDateTime := findDateTime; tmpDateTime.After(minDateTime) || tmpDateTime.Equal(minDateTime); tmpDateTime.AddDate(0, 0, -1) {
+					tmpDate := tmpDateTime.Format(utils.FormatDate)
+					if _, ok := edbDataMap[edbInfoId][tmpDate]; ok { //如果能找到数据,那么就返回
+						findDate = tmpDate
+						break
+					}
+				}
+			default:
+				err = errors.New(fmt.Sprint("日期类型异常,Type:", barChartInfoDate.Type))
+				return
+			}
+			if tmpValue, ok := edbDataMap[edbInfoId][findDate]; ok {
+				dateData[edbInfoId] = tmpValue
+			} else {
+				// 没有数据的指标id
+				notDataEdbIdList = append(notDataEdbIdList, edbInfoId)
+			}
+		}
+
+		//Sort int    `description:"排序类型,0:默认,1:升序,2:降序"`
+		// 排序
+		dateDataSort := utils.NewMapSorter(dateData)
+		sort.Sort(dateDataSort)
+		if barChartInfoSort.Sort == 1 {
+			// 先将没有数据的指标id放在最前面
+			if len(notDataEdbIdList) > 0 {
+				edbIdList = append(edbIdList, notDataEdbIdList...)
+			}
+			for _, v := range dateDataSort {
+				edbIdList = append(edbIdList, v.Key)
+			}
+		} else {
+			for i := len(dateDataSort) - 1; i >= 0; i-- {
+				edbIdList = append(edbIdList, dateDataSort[i].Key)
+			}
+			// 再将没有数据的指标id放在最后面
+			if len(notDataEdbIdList) > 0 {
+				edbIdList = append(edbIdList, notDataEdbIdList...)
+			}
+		}
+	}
+
+	yDataList = make([]chart_info.YData, 0) //y轴的数据列表
+
+	for _, barChartInfoDate := range barChartInfoDateList {
+		var maxDate time.Time
+
+		findDataList := make([]float64, 0) // 当前日期的数据值
+		for _, edbInfoId := range edbIdList {
+			findDate := barChartInfoDate.Date     //需要的日期值
+			dataList := edbDataListMap[edbInfoId] //指标的所有数据值
+			switch barChartInfoDate.Type {
+			case 1: //最新值
+				dataList := edbDataListMap[edbInfoId]
+				findDate = dataList[len(dataList)-1].DataTime
+			case 2: //近期几天
+				findDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, dataList[len(dataList)-1].DataTime, time.Local)
+				if tmpErr != nil {
+					err = tmpErr
+					return
+				}
+				findDateTime = findDateTime.AddDate(0, 0, -barChartInfoDate.Value)
+
+				lenData := len(dataList) - 1
+				for i := lenData; i >= 0; i-- {
+					currDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, dataList[i].DataTime, time.Local)
+					if tmpErr != nil {
+						err = tmpErr
+						return
+					}
+					if utils.GetTimeSubDay(currDateTime, findDateTime) >= 5 {
+						findDate = dataList[i].DataTime
+						break
+					}
+				}
+			case 3: // 固定日期
+				//最早的日期
+				minDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, dataList[0].DataTime, time.Local)
+				if tmpErr != nil {
+					err = tmpErr
+					return
+				}
+				//寻找固定日期的数据
+				findDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, barChartInfoDate.Date, time.Local)
+				if tmpErr != nil {
+					err = tmpErr
+					return
+				}
+				for tmpDateTime := findDateTime; tmpDateTime.After(minDateTime) || tmpDateTime.Equal(minDateTime); tmpDateTime.AddDate(0, 0, -1) {
+					tmpDate := tmpDateTime.Format(utils.FormatDate)
+					if _, ok := edbDataMap[edbInfoId][tmpDate]; ok { //如果能找到数据,那么就返回
+						findDate = tmpDate
+						break
+					}
+				}
+			default:
+				err = errors.New(fmt.Sprint("日期类型异常,Type:", barChartInfoDate.Type))
+				return
+			}
+			findDateTime, _ := time.ParseInLocation(utils.FormatDate, findDate, time.Local)
+			if maxDate.IsZero() {
+				maxDate = findDateTime
+			} else {
+				if findDateTime.After(maxDate) {
+					maxDate = findDateTime
+				}
+			}
+			if tmpValue, ok := edbDataMap[edbInfoId][findDate]; ok {
+				findDataList = append(findDataList, tmpValue)
+			} else {
+				findDataList = append(findDataList, 0)
+			}
+		}
+
+		yDataList = append(yDataList, chart_info.YData{
+			Date:  maxDate.Format(utils.FormatDate),
+			Value: findDataList,
+			Color: barChartInfoDate.Color,
+		})
+	}
+
 	return
 }
 

+ 52 - 0
utils/common.go

@@ -1024,3 +1024,55 @@ func JoinStr2IntArr(str, sep string) (arr []int) {
 	}
 	return
 }
+
+// GetTimeSubDay 计算两个时间的自然日期差
+func GetTimeSubDay(t1, t2 time.Time) int {
+	var day int
+	swap := false
+	if t1.Unix() > t2.Unix() {
+		t1, t2 = t2, t1
+		swap = true
+	}
+
+	t1_ := t1.Add(time.Duration(t2.Sub(t1).Milliseconds()%86400000) * time.Millisecond)
+	day = int(t2.Sub(t1).Hours() / 24)
+	// 计算在t1+两个时间的余数之后天数是否有变化
+	if t1_.Day() != t1.Day() {
+		day += 1
+	}
+
+	if swap {
+		day = -day
+	}
+
+	return day
+}
+
+// MapSorter 对于map 排序
+type MapSorter []Item
+
+type Item struct {
+	Key int
+	Val float64
+}
+
+func NewMapSorter(m map[int]float64) MapSorter {
+	ms := make(MapSorter, 0, len(m))
+	for k, v := range m {
+		ms = append(ms, Item{k, v})
+	}
+	return ms
+}
+
+func (ms MapSorter) Len() int {
+	return len(ms)
+}
+
+func (ms MapSorter) Less(i, j int) bool {
+	return ms[i].Val > ms[j].Val // 按值排序
+	//return ms[i].Key < ms[j].Key // 按键排序
+}
+
+func (ms MapSorter) Swap(i, j int) {
+	ms[i], ms[j] = ms[j], ms[i]
+}