|
@@ -0,0 +1,1593 @@
|
|
|
+package services
|
|
|
+
|
|
|
+import (
|
|
|
+ "encoding/json"
|
|
|
+ "errors"
|
|
|
+ "eta/eta_forum_admin/models"
|
|
|
+ "eta/eta_forum_admin/models/data"
|
|
|
+ "eta/eta_forum_admin/utils"
|
|
|
+ "fmt"
|
|
|
+ "github.com/shopspring/decimal"
|
|
|
+ "math"
|
|
|
+ "sort"
|
|
|
+ "strconv"
|
|
|
+ "time"
|
|
|
+)
|
|
|
+
|
|
|
+type ChartInfoReq struct {
|
|
|
+ ChartInfoId int `description:"图表id,新增时传0"`
|
|
|
+}
|
|
|
+
|
|
|
+// DeleteChartInfoDataRedis 清除图表缓存
|
|
|
+func DeleteChartInfoDataRedis(bodyByte []byte) (err error) {
|
|
|
+ var req ChartInfoReq
|
|
|
+ err = json.Unmarshal(bodyByte, &req)
|
|
|
+ if err != nil {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if req.ChartInfoId > 0 {
|
|
|
+ err = utils.Rc.Delete(GetChartInfoDataKey(req.ChartInfoId))
|
|
|
+ }
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+// DeleteChartClassifyRedis 清除图表分类缓存
|
|
|
+func DeleteChartClassifyRedis(bodyByte []byte) (err error) {
|
|
|
+ err = utils.Rc.Delete(utils.CACHE_CHART_CLASSIFY)
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+// GetChartInfoDataKey 获取图表缓存的key
|
|
|
+func GetChartInfoDataKey(chartInfoId int) string {
|
|
|
+ key := fmt.Sprint(utils.CACHE_CHART_INFO_DATA, chartInfoId)
|
|
|
+ return key
|
|
|
+}
|
|
|
+
|
|
|
+// GetChartEdbData 获取图表的指标数据
|
|
|
+func GetChartEdbData(chartInfoId, chartType int, calendar, startDate, endDate string, mappingList []*models.ChartEdbInfoMapping, extraConfigStr string, 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 7: // 柱形图
|
|
|
+ var barConfig models.BarChartInfoReq
|
|
|
+ if extraConfigStr == `` {
|
|
|
+ errMsg = "柱方图未配置"
|
|
|
+ err = errors.New(errMsg)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ err = json.Unmarshal([]byte(extraConfigStr), &barConfig)
|
|
|
+ if err != nil {
|
|
|
+ errMsg = "柱方图配置异常"
|
|
|
+ err = errors.New(errMsg)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ extraConfig = barConfig
|
|
|
+ case 10: // 截面散点图
|
|
|
+ var tmpExtraConfig models.SectionScatterReq
|
|
|
+ if extraConfigStr == `` {
|
|
|
+ errMsg = "截面散点图未配置"
|
|
|
+ err = errors.New(errMsg)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ err = json.Unmarshal([]byte(extraConfigStr), &tmpExtraConfig)
|
|
|
+ if err != nil {
|
|
|
+ errMsg = "截面散点配置异常"
|
|
|
+ err = errors.New(errMsg)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ extraConfig = tmpExtraConfig
|
|
|
+ case utils.CHART_TYPE_RADAR:
|
|
|
+ var barConfig models.RadarChartInfoReq
|
|
|
+ if extraConfigStr == `` {
|
|
|
+ errMsg = "雷达图未配置"
|
|
|
+ err = errors.New(errMsg)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ err = json.Unmarshal([]byte(extraConfigStr), &barConfig)
|
|
|
+ if err != nil {
|
|
|
+ errMsg = "雷达图配置异常"
|
|
|
+ err = errors.New(errMsg)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ extraConfig = barConfig
|
|
|
+ default:
|
|
|
+ xEdbIdValue = make([]int, 0)
|
|
|
+ yDataList = make([]models.YData, 0)
|
|
|
+ }
|
|
|
+
|
|
|
+ // 指标对应的所有数据
|
|
|
+ edbDataListMap, edbList, err := getEdbDataMapList(chartInfoId, chartType, calendar, startDate, endDate, mappingList, seasonExtraConfig)
|
|
|
+ if err != nil {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 特殊图形数据处理
|
|
|
+ switch chartType {
|
|
|
+ case 7: // 柱形图
|
|
|
+ barChartConf := extraConfig.(models.BarChartInfoReq)
|
|
|
+ xEdbIdValue, yDataList, err = BarChartData(mappingList, edbDataListMap, barChartConf.DateList, barChartConf.Sort)
|
|
|
+
|
|
|
+ for k := range yDataList {
|
|
|
+ yDataList[k].Unit = barChartConf.Unit
|
|
|
+ yDataList[k].UnitEn = barChartConf.UnitEn
|
|
|
+ }
|
|
|
+
|
|
|
+ for _, v := range edbList {
|
|
|
+ // 指标别名
|
|
|
+ if barChartConf.EdbInfoIdList != nil && len(barChartConf.EdbInfoIdList) > 0 {
|
|
|
+ for _, reqEdb := range barChartConf.EdbInfoIdList {
|
|
|
+ if v.EdbInfoId == reqEdb.EdbInfoId {
|
|
|
+ v.EdbAliasName = reqEdb.Name
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ case 10: // 截面散点图
|
|
|
+ sectionScatterConf := extraConfig.(models.SectionScatterReq)
|
|
|
+ xEdbIdValue, dataResp, err = GetSectionScatterChartData(chartInfoId, mappingList, edbDataListMap, sectionScatterConf)
|
|
|
+
|
|
|
+ var tmpExtraConfig models.SectionScatterReq
|
|
|
+ if extraConfigStr == `` {
|
|
|
+ errMsg = "截面散点图未配置"
|
|
|
+ err = errors.New(errMsg)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ err = json.Unmarshal([]byte(extraConfigStr), &tmpExtraConfig)
|
|
|
+ if err != nil {
|
|
|
+ errMsg = "截面散点配置异常"
|
|
|
+ err = errors.New(errMsg)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 这个数据没有必要返回给前端
|
|
|
+ for _, v := range edbList {
|
|
|
+ v.DataList = nil
|
|
|
+ }
|
|
|
+ case utils.CHART_TYPE_RADAR: //雷达图
|
|
|
+ radarConf := extraConfig.(models.RadarChartInfoReq)
|
|
|
+ xEdbIdValue, dataResp, err = RadarChartData(mappingList, edbDataListMap, radarConf)
|
|
|
+ }
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+// GetEdbDataMapList 获取指标最后的基础数据
|
|
|
+func GetEdbDataMapList(chartInfoId, chartType int, calendar, startDate, endDate string, mappingList []*models.ChartEdbInfoMapping, seasonExtra string) (edbDataListMap map[int][]*models.EdbDataList, edbList []*models.ChartEdbInfoMapping, err error) {
|
|
|
+ edbDataListMap, edbList, err = getEdbDataMapList(chartInfoId, chartType, calendar, startDate, endDate, mappingList, seasonExtra)
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+// getEdbDataMapList 获取指标最后的基础数据
|
|
|
+func getEdbDataMapList(chartInfoId, chartType int, calendar, startDate, endDate string, mappingList []*models.ChartEdbInfoMapping, seasonExtraConfig string) (edbDataListMap map[int][]*models.EdbDataList, edbList []*models.ChartEdbInfoMapping, err error) {
|
|
|
+ // 指标对应的所有数据
|
|
|
+ edbDataListMap = make(map[int][]*models.EdbDataList)
|
|
|
+
|
|
|
+ for _, v := range mappingList {
|
|
|
+ //fmt.Println("v:", v.EdbInfoId)
|
|
|
+ item := new(models.ChartEdbInfoMapping)
|
|
|
+ item.EdbInfoId = v.EdbInfoId
|
|
|
+ item.SourceName = v.SourceName
|
|
|
+ item.Source = v.Source
|
|
|
+ item.EdbCode = v.EdbCode
|
|
|
+ item.EdbName = v.EdbName
|
|
|
+ item.EdbNameEn = v.EdbNameEn
|
|
|
+ item.Frequency = v.Frequency
|
|
|
+ item.EdbType = v.EdbType
|
|
|
+ item.FrequencyEn = GetFrequencyEn(v.Frequency)
|
|
|
+ if v.Unit != `无` {
|
|
|
+ item.Unit = v.Unit
|
|
|
+ }
|
|
|
+ item.UnitEn = v.UnitEn
|
|
|
+ item.StartDate = v.StartDate
|
|
|
+ item.EndDate = v.EndDate
|
|
|
+ item.ModifyTime = v.ModifyTime
|
|
|
+ item.EdbInfoCategoryType = v.EdbInfoCategoryType
|
|
|
+ item.PredictChartColor = v.PredictChartColor
|
|
|
+ item.ClassifyId = v.ClassifyId
|
|
|
+ if chartInfoId <= 0 {
|
|
|
+ item.IsAxis = 1
|
|
|
+ item.LeadValue = 0
|
|
|
+ item.LeadUnit = ""
|
|
|
+ item.ChartEdbMappingId = 0
|
|
|
+ item.ChartInfoId = 0
|
|
|
+ item.IsOrder = false
|
|
|
+ item.EdbInfoType = 1
|
|
|
+ item.ChartStyle = ""
|
|
|
+ item.ChartColor = ""
|
|
|
+ item.ChartWidth = 0
|
|
|
+ item.MaxData = v.MaxValue
|
|
|
+ item.MinData = v.MinValue
|
|
|
+ } else {
|
|
|
+ item.IsAxis = v.IsAxis
|
|
|
+ item.EdbInfoType = v.EdbInfoType
|
|
|
+ item.LeadValue = v.LeadValue
|
|
|
+ item.LeadUnit = v.LeadUnit
|
|
|
+ item.LeadUnitEn = GetLeadUnitEn(v.LeadUnit)
|
|
|
+ item.ChartEdbMappingId = v.ChartEdbMappingId
|
|
|
+ item.ChartInfoId = v.ChartInfoId
|
|
|
+ item.ChartStyle = v.ChartStyle
|
|
|
+ item.ChartColor = v.ChartColor
|
|
|
+ item.ChartWidth = v.ChartWidth
|
|
|
+ item.IsOrder = v.IsOrder
|
|
|
+ item.MaxData = v.MaxData
|
|
|
+ item.MinData = v.MinData
|
|
|
+ }
|
|
|
+ item.LatestValue = v.LatestValue
|
|
|
+ item.LatestDate = v.LatestDate
|
|
|
+ item.UniqueCode = v.UniqueCode
|
|
|
+ item.MoveLatestDate = v.LatestDate
|
|
|
+ item.EdbAliasName = v.EdbAliasName
|
|
|
+ item.IsConvert = v.IsConvert
|
|
|
+ item.ConvertType = v.ConvertType
|
|
|
+ item.ConvertValue = v.ConvertValue
|
|
|
+ item.ConvertUnit = v.ConvertUnit
|
|
|
+ item.ConvertEnUnit = v.ConvertEnUnit
|
|
|
+ item.IsJoinPermission = v.IsJoinPermission
|
|
|
+
|
|
|
+ var startDateReal string
|
|
|
+ var diffSeconds int64
|
|
|
+ if chartType == 2 { //季节性图
|
|
|
+ startDateReal = startDate
|
|
|
+ } else {
|
|
|
+ if v.EdbInfoType == 0 && v.LeadUnit != "" && v.LeadValue > 0 { //领先指标
|
|
|
+ var startTimeRealTemp time.Time
|
|
|
+ startDateParse, _ := time.Parse(utils.FormatDate, startDate)
|
|
|
+ switch v.LeadUnit {
|
|
|
+ case "天":
|
|
|
+ startTimeRealTemp = startDateParse.AddDate(0, 0, -v.LeadValue)
|
|
|
+ case "月":
|
|
|
+ startTimeRealTemp = startDateParse.AddDate(0, -v.LeadValue, 0)
|
|
|
+ case "季":
|
|
|
+ startTimeRealTemp = startDateParse.AddDate(0, -3*v.LeadValue, 0)
|
|
|
+ case "周":
|
|
|
+ startTimeRealTemp = startDateParse.AddDate(0, 0, -7*v.LeadValue)
|
|
|
+ case "年":
|
|
|
+ startTimeRealTemp = startDateParse.AddDate(-v.LeadValue, 0, 0)
|
|
|
+ }
|
|
|
+ if startTimeRealTemp.Before(startDateParse) {
|
|
|
+ startDateReal = startTimeRealTemp.Format(utils.FormatDate)
|
|
|
+ diffSeconds = (int64(startTimeRealTemp.UnixNano()) - int64(startDateParse.UnixNano())) / 1e6
|
|
|
+ } else {
|
|
|
+ startDateReal = startDate
|
|
|
+ diffSeconds = 0
|
|
|
+ }
|
|
|
+
|
|
|
+ // todo 预测指标的开始日期也要偏移
|
|
|
+ /*{
|
|
|
+ day, tmpErr := utils.GetDaysBetween2Date(utils.FormatDate, startDate, startDateReal)
|
|
|
+ if tmpErr != nil {
|
|
|
+ err = tmpErr
|
|
|
+ return
|
|
|
+ }
|
|
|
+ moveLatestDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, item.MoveLatestDate, time.Local)
|
|
|
+ if tmpErr != nil {
|
|
|
+ err = tmpErr
|
|
|
+ return
|
|
|
+ }
|
|
|
+ item.MoveLatestDate = moveLatestDateTime.AddDate(0, 0, day).Format(utils.FormatDate)
|
|
|
+ }*/
|
|
|
+ } else {
|
|
|
+ startDateReal = startDate
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //fmt.Println("line 1011 chart:", v.Source, v.EdbInfoId, startDateReal, endDate)
|
|
|
+ calendarPreYear := 0
|
|
|
+ if calendar == "农历" {
|
|
|
+ newStartDateReal, err := time.Parse(utils.FormatDate, startDateReal)
|
|
|
+ if err != nil {
|
|
|
+ fmt.Println("time.Parse:" + err.Error())
|
|
|
+ }
|
|
|
+ calendarPreYear = newStartDateReal.Year() - 1
|
|
|
+ newStartDateReal = newStartDateReal.AddDate(-1, 0, 0)
|
|
|
+ startDateReal = newStartDateReal.Format(utils.FormatDate)
|
|
|
+ }
|
|
|
+ dataList := make([]*models.EdbDataList, 0)
|
|
|
+ //fmt.Println("chart:", v.Source, v.EdbInfoId, startDateReal, endDate)
|
|
|
+ //fmt.Println("calendarPreYear:", calendarPreYear)
|
|
|
+ //var newEdbInfo *models.EdbInfo
|
|
|
+ switch v.EdbInfoCategoryType {
|
|
|
+ case 0:
|
|
|
+ dataList, err = GetEdbDataList(v.EdbInfoId, startDateReal, endDate)
|
|
|
+ case 1:
|
|
|
+ // _, dataList, _, _, err, _ = GetPredictDataListByPredictEdbInfoId(v.EdbInfoId, startDateReal, endDate, true)
|
|
|
+ default:
|
|
|
+ err = errors.New(fmt.Sprint("获取失败,指标类型异常", v.EdbInfoCategoryType))
|
|
|
+ }
|
|
|
+ if err != nil {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ if v.IsConvert == 1 {
|
|
|
+ switch v.ConvertType {
|
|
|
+ case 1:
|
|
|
+ for i, data := range dataList {
|
|
|
+ dataList[i].Value = data.Value * v.ConvertValue
|
|
|
+ }
|
|
|
+ //item.MaxData = item.MaxData * v.ConvertValue
|
|
|
+ //item.MinData = item.MinData * v.ConvertValue
|
|
|
+ case 2:
|
|
|
+ for i, data := range dataList {
|
|
|
+ dataList[i].Value = data.Value / v.ConvertValue
|
|
|
+ }
|
|
|
+ //item.MaxData = item.MaxData / v.ConvertValue
|
|
|
+ //item.MinData = item.MinData / v.ConvertValue
|
|
|
+ case 3:
|
|
|
+ for i, data := range dataList {
|
|
|
+ if data.Value <= 0 {
|
|
|
+ err = errors.New("数据中含有负数或0,无法对数运算")
|
|
|
+ return
|
|
|
+ }
|
|
|
+ dataList[i].Value = math.Log(data.Value) / math.Log(v.ConvertValue)
|
|
|
+ }
|
|
|
+ //item.MaxData = math.Log(item.MaxData) / math.Log(v.ConvertValue)
|
|
|
+ //item.MinData = math.Log(item.MinData) / math.Log(v.ConvertValue)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ edbDataListMap[v.EdbInfoId] = dataList
|
|
|
+
|
|
|
+ if diffSeconds != 0 && v.EdbInfoType == 0 {
|
|
|
+ dataListLen := len(dataList)
|
|
|
+ for i := 0; i < dataListLen; i++ {
|
|
|
+ dataList[i].DataTimestamp = dataList[i].DataTimestamp - diffSeconds
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if chartType == 2 {
|
|
|
+ latestDate, tmpErr := time.Parse(utils.FormatDate, v.LatestDate)
|
|
|
+ if tmpErr != nil {
|
|
|
+ //item.DataList = dataList
|
|
|
+ item.IsNullData = true
|
|
|
+ edbList = append(edbList, item)
|
|
|
+ continue
|
|
|
+ err = errors.New(fmt.Sprint("获取最后实际数据的日期失败,Err:" + tmpErr.Error() + ";LatestDate:" + v.LatestDate))
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ if calendar == "农历" {
|
|
|
+ if len(dataList) <= 0 {
|
|
|
+ result := new(data.EdbDataResult)
|
|
|
+ item.DataList = result
|
|
|
+ } else {
|
|
|
+ result, tmpErr := data.AddCalculateQuarterV6(dataList)
|
|
|
+ if tmpErr != nil {
|
|
|
+ err = errors.New("获取农历数据失败,Err:" + tmpErr.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+ quarterDataList, tErr := GetSeasonEdbInfoDataListByXDateNong(result, latestDate, seasonExtraConfig, calendarPreYear)
|
|
|
+ if tErr != nil {
|
|
|
+ err = errors.New("获取季节性图表数据失败,Err:" + tErr.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+ item.DataList = quarterDataList
|
|
|
+ }
|
|
|
+
|
|
|
+ } else {
|
|
|
+ quarterDataList, tErr := GetSeasonEdbInfoDataListByXDate(dataList, latestDate, seasonExtraConfig)
|
|
|
+ if tErr != nil {
|
|
|
+ err = errors.New("获取季节性图表数据失败,Err:" + tErr.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+ item.DataList = quarterDataList
|
|
|
+ }
|
|
|
+
|
|
|
+ } else if chartType == 7 || chartType == utils.CHART_TYPE_RADAR { //柱方图
|
|
|
+ //item.DataList = dataList
|
|
|
+ } else {
|
|
|
+ item.DataList = dataList
|
|
|
+ }
|
|
|
+ edbList = append(edbList, item)
|
|
|
+ }
|
|
|
+
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+// GetSeasonEdbInfoDataListByXDate 季节性图的指标数据根据横轴展示
|
|
|
+func GetSeasonEdbInfoDataListByXDate(dataList []*models.EdbDataList, latestDate time.Time, seasonExtraConfig string) (quarterDataListSort models.QuarterDataList, err error) {
|
|
|
+ xStartDate := "01-01"
|
|
|
+ xEndDate := "12-31"
|
|
|
+ jumpYear := 0
|
|
|
+ legends := make([]models.SeasonChartLegend, 0)
|
|
|
+ var seasonExtra models.SeasonExtraItem
|
|
|
+ if seasonExtraConfig != "" {
|
|
|
+ err = json.Unmarshal([]byte(seasonExtraConfig), &seasonExtra)
|
|
|
+ if err != nil {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if seasonExtra.XStartDate != "" {
|
|
|
+ xStartDate = seasonExtra.XStartDate
|
|
|
+ xEndDate = seasonExtra.XEndDate
|
|
|
+ jumpYear = seasonExtra.JumpYear
|
|
|
+ legends = seasonExtra.ChartLegend
|
|
|
+ }
|
|
|
+
|
|
|
+ length := len(dataList)
|
|
|
+ if length == 0 {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ legendMap := make(map[string]string, 0)
|
|
|
+ if len(legends) > 0 {
|
|
|
+ for _, v := range legends {
|
|
|
+ legendMap[v.Name] = v.Value
|
|
|
+ }
|
|
|
+ }
|
|
|
+ latestDateStr := latestDate.Format(utils.FormatDate)
|
|
|
+
|
|
|
+ //判断横轴的两个时间之间是不是跨年了,如果跨年了,则横轴截止年份比起始年份+1,如果不跨年,截止年份等于起始年份
|
|
|
+ //根据数据确定最早的年份,和最近年份
|
|
|
+ //根据横轴的日期,汇总所有的年份
|
|
|
+ startDate := dataList[0].DataTime
|
|
|
+ startDateT, tmpErr := time.Parse(utils.FormatDate, startDate)
|
|
|
+ if tmpErr != nil {
|
|
|
+ err = tmpErr
|
|
|
+ return
|
|
|
+ }
|
|
|
+ startYear := startDateT.Year()
|
|
|
+ //获取数据的最新日期
|
|
|
+ lastDate := dataList[length-1].DataTime
|
|
|
+ lastDateT, tmpErr := time.Parse(utils.FormatDate, lastDate)
|
|
|
+ if tmpErr != nil {
|
|
|
+ err = tmpErr
|
|
|
+ return
|
|
|
+ }
|
|
|
+ endYear := lastDateT.Year()
|
|
|
+ nowYear := time.Now().Year()
|
|
|
+ dataMap := make(map[string]models.QuarterXDateItem, 0)
|
|
|
+
|
|
|
+ quarterDataList := make([]*models.QuarterData, 0)
|
|
|
+ quarterMap := make(map[string][]*models.EdbDataList, 0)
|
|
|
+
|
|
|
+ //整理出日期
|
|
|
+ idx := 1
|
|
|
+ chartLegendMap := make(map[string]int, 0)
|
|
|
+ for currentStartYear := startYear; currentStartYear <= endYear; currentStartYear++ {
|
|
|
+ startStr := fmt.Sprintf("%d-%s", currentStartYear, xStartDate)
|
|
|
+ currentEndYear := currentStartYear
|
|
|
+ if jumpYear == 1 {
|
|
|
+ currentEndYear = currentStartYear + 1
|
|
|
+ }
|
|
|
+ endStr := fmt.Sprintf("%d-%s", currentEndYear, xEndDate)
|
|
|
+ name := fmt.Sprintf("%s_%s", startStr, endStr)
|
|
|
+ showName := fmt.Sprintf("%d_%d", currentStartYear, currentEndYear)
|
|
|
+
|
|
|
+ startT, tEr := time.Parse(utils.FormatDate, startStr)
|
|
|
+ if tEr != nil {
|
|
|
+ err = tEr
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ endT, tEr := time.Parse(utils.FormatDate, endStr)
|
|
|
+ if tEr != nil {
|
|
|
+ err = tEr
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ if lastDateT.Before(startT) {
|
|
|
+ //如果最新的日期在起始日之前,则跳出循环
|
|
|
+ break
|
|
|
+ }
|
|
|
+
|
|
|
+ if endT.Year() > nowYear {
|
|
|
+ //如果最新的日期比真实年份要大,则数据全部按照最大的年份补齐
|
|
|
+ nowYear = endT.Year()
|
|
|
+ }
|
|
|
+
|
|
|
+ item := models.QuarterXDateItem{
|
|
|
+ StartDate: startT,
|
|
|
+ EndDate: endT,
|
|
|
+ ShowName: showName,
|
|
|
+ }
|
|
|
+ dataMap[name] = item
|
|
|
+ chartLegendMap[name] = idx
|
|
|
+ idx++
|
|
|
+ fmt.Println("年份" + showName + "日期" + startStr + " " + endStr)
|
|
|
+ if lastDateT.Before(endT) {
|
|
|
+ //如果最新的日期在起始日之前,则跳出循环
|
|
|
+ break
|
|
|
+ }
|
|
|
+ }
|
|
|
+ lenYear := len(dataMap)
|
|
|
+ for k, v := range dataMap {
|
|
|
+ if i, ok := chartLegendMap[k]; ok {
|
|
|
+ v.ChartLegend = strconv.Itoa(endYear - lenYear + i)
|
|
|
+ }
|
|
|
+ dataMap[k] = v
|
|
|
+ }
|
|
|
+
|
|
|
+ for _, v := range dataList {
|
|
|
+ dataTimeT, _ := time.Parse(utils.FormatDate, v.DataTime)
|
|
|
+ year := dataTimeT.Year()
|
|
|
+ newItemDate := dataTimeT.AddDate(nowYear-year, 0, 0)
|
|
|
+ for k, dateItem := range dataMap {
|
|
|
+ tmpVal := models.EdbDataList{
|
|
|
+ EdbDataId: v.EdbDataId,
|
|
|
+ EdbInfoId: v.EdbInfoId,
|
|
|
+ DataTime: v.DataTime,
|
|
|
+ DataTimestamp: v.DataTimestamp,
|
|
|
+ Value: v.Value,
|
|
|
+ }
|
|
|
+ if (dateItem.StartDate.Before(dataTimeT) && dateItem.EndDate.After(dataTimeT)) || dateItem.StartDate == dataTimeT || dateItem.EndDate == dataTimeT {
|
|
|
+ if jumpYear == 1 {
|
|
|
+ //计算前一年最大的日期, 只补齐数据到去年
|
|
|
+ beforeYearMaxDate := fmt.Sprintf("%d-12-31", dateItem.StartDate.Year())
|
|
|
+ beforeYearMaxDateT, _ := time.Parse(utils.FormatDate, beforeYearMaxDate)
|
|
|
+ if dataTimeT.Before(beforeYearMaxDateT) || dataTimeT == beforeYearMaxDateT {
|
|
|
+ newItemDate = dataTimeT.AddDate(nowYear-year-1, 0, 0)
|
|
|
+ } else {
|
|
|
+ newItemDate = dataTimeT.AddDate(nowYear-year, 0, 0)
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ newItemDate = dataTimeT.AddDate(nowYear-year, 0, 0)
|
|
|
+ }
|
|
|
+ timestamp := newItemDate.UnixNano() / 1e6
|
|
|
+ tmpVal.DataTimestamp = timestamp
|
|
|
+ tmpV := &tmpVal
|
|
|
+ if findVal, ok := quarterMap[k]; !ok {
|
|
|
+ findVal = append(findVal, tmpV)
|
|
|
+ quarterMap[k] = findVal
|
|
|
+ } else {
|
|
|
+ findVal = append(findVal, tmpV)
|
|
|
+ quarterMap[k] = findVal
|
|
|
+ }
|
|
|
+
|
|
|
+ if v.DataTime == latestDateStr {
|
|
|
+ dateItem.CuttingDataTimestamp = timestamp
|
|
|
+ dataMap[k] = dateItem
|
|
|
+ }
|
|
|
+ //break
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ for k, v := range dataMap {
|
|
|
+ itemList := quarterMap[k]
|
|
|
+ quarterItem := new(models.QuarterData)
|
|
|
+ quarterItem.Years = v.ShowName
|
|
|
+ quarterItem.ChartLegend = v.ChartLegend
|
|
|
+ if le, ok := legendMap[v.ShowName]; ok {
|
|
|
+ if le != strconv.Itoa(v.StartDate.Year()) && le != strconv.Itoa(v.EndDate.Year()) {
|
|
|
+ quarterItem.ChartLegend = le
|
|
|
+ }
|
|
|
+ }
|
|
|
+ quarterItem.DataList = itemList
|
|
|
+ quarterItem.CuttingDataTimestamp = v.CuttingDataTimestamp
|
|
|
+
|
|
|
+ //如果等于最后的实际日期,那么将切割时间戳记录
|
|
|
+ if quarterItem.CuttingDataTimestamp == 0 {
|
|
|
+ //如果大于最后的实际日期,那么第一个点就是切割的时间戳
|
|
|
+ if latestDate.Before(v.StartDate) && len(itemList) > 0 {
|
|
|
+ quarterItem.CuttingDataTimestamp = itemList[0].DataTimestamp - 100
|
|
|
+ }
|
|
|
+ }
|
|
|
+ quarterDataList = append(quarterDataList, quarterItem)
|
|
|
+ }
|
|
|
+
|
|
|
+ if len(quarterDataList) > 0 {
|
|
|
+ quarterDataListSort = quarterDataList
|
|
|
+ sort.Sort(quarterDataListSort)
|
|
|
+ }
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+// GetSeasonEdbInfoDataListByXDateNong 季节性图的指标数据根据横轴选择农历时展示
|
|
|
+func GetSeasonEdbInfoDataListByXDateNong(result *data.EdbDataResult, latestDate time.Time, seasonExtraConfig string, calendarPreYear int) (quarterDataListSort models.QuarterDataList, err error) {
|
|
|
+ xStartDate := "01-01"
|
|
|
+ xEndDate := "12-31"
|
|
|
+ jumpYear := 0
|
|
|
+ legends := make([]models.SeasonChartLegend, 0)
|
|
|
+ var seasonExtra models.SeasonExtraItem
|
|
|
+ if seasonExtraConfig != "" {
|
|
|
+ err = json.Unmarshal([]byte(seasonExtraConfig), &seasonExtra)
|
|
|
+ if err != nil {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if seasonExtra.XStartDate != "" {
|
|
|
+ xStartDate = seasonExtra.XStartDate
|
|
|
+ xEndDate = seasonExtra.XEndDate
|
|
|
+ jumpYear = seasonExtra.JumpYear
|
|
|
+ legends = seasonExtra.ChartLegend
|
|
|
+ }
|
|
|
+
|
|
|
+ length := len(result.List)
|
|
|
+ if length == 0 {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ legendMap := make(map[string]string, 0)
|
|
|
+ if len(legends) > 0 {
|
|
|
+ for _, v := range legends {
|
|
|
+ legendMap[v.Name] = v.Value
|
|
|
+ }
|
|
|
+ }
|
|
|
+ latestDateYear := latestDate.Year()
|
|
|
+ //判断横轴的两个时间之间是不是跨年了,如果跨年了,则横轴截止年份比起始年份+1,如果不跨年,截止年份等于起始年份
|
|
|
+ //根据数据确定最早的年份,和最近年份
|
|
|
+ //根据横轴的日期,汇总所有的年份
|
|
|
+
|
|
|
+ startYear := result.List[0].Year
|
|
|
+ /*if jumpYear == 1 {
|
|
|
+ if startYear != calendarPreYear {
|
|
|
+ startYear = startYear - 1
|
|
|
+ }
|
|
|
+ }*/
|
|
|
+
|
|
|
+ itemLength := len(result.List[length-1].Items)
|
|
|
+ //获取数据的最新日期
|
|
|
+ lastDate := result.List[length-1].Items[itemLength-1].DataTime
|
|
|
+ maxY := result.List[length-1].Year
|
|
|
+ lastDateT, tmpErr := time.Parse(utils.FormatDate, lastDate)
|
|
|
+ if tmpErr != nil {
|
|
|
+ err = tmpErr
|
|
|
+ return
|
|
|
+ }
|
|
|
+ endYear := lastDateT.Year()
|
|
|
+ nowYear := time.Now().Year()
|
|
|
+ dataMap := make(map[string]models.QuarterXDateItem, 0)
|
|
|
+
|
|
|
+ quarterDataList := make([]*models.QuarterData, 0)
|
|
|
+ resultData := make([]*models.QuarterData, 0)
|
|
|
+ quarterMap := make(map[string][]*models.EdbDataList, 0)
|
|
|
+
|
|
|
+ //整理出日期
|
|
|
+ var startTmpT, endTmpT time.Time
|
|
|
+ idx := 1
|
|
|
+ chartLegendMap := make(map[string]int, 0)
|
|
|
+ for currentStartYear := startYear; currentStartYear <= endYear; currentStartYear++ {
|
|
|
+ startStr := fmt.Sprintf("%d-%s", currentStartYear, xStartDate)
|
|
|
+ currentEndYear := currentStartYear
|
|
|
+ if jumpYear == 1 {
|
|
|
+ currentEndYear = currentStartYear + 1
|
|
|
+ }
|
|
|
+ endStr := fmt.Sprintf("%d-%s", currentEndYear, xEndDate)
|
|
|
+ showName := fmt.Sprintf("%d_%d", currentStartYear, currentEndYear)
|
|
|
+
|
|
|
+ startT, tEr := time.Parse(utils.FormatDate, startStr)
|
|
|
+ if tEr != nil {
|
|
|
+ err = tEr
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ endT, tEr := time.Parse(utils.FormatDate, endStr)
|
|
|
+ if tEr != nil {
|
|
|
+ err = tEr
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ if lastDateT.Before(startT) {
|
|
|
+ //如果最新的日期在起始日之前,则跳出循环
|
|
|
+ break
|
|
|
+ }
|
|
|
+ if endT.Year() > nowYear {
|
|
|
+ //如果最新的日期比真实年份要大,则数据全部按照最大的年份补齐
|
|
|
+ nowYear = endT.Year()
|
|
|
+ }
|
|
|
+ item := models.QuarterXDateItem{
|
|
|
+ StartDate: startT,
|
|
|
+ EndDate: endT,
|
|
|
+ ShowName: showName,
|
|
|
+ }
|
|
|
+ dataMap[showName] = item
|
|
|
+ fmt.Println("年份" + showName + "日期" + startStr + " " + endStr)
|
|
|
+ startTmpT = startT
|
|
|
+ endTmpT = endT
|
|
|
+ chartLegendMap[showName] = idx
|
|
|
+ idx++
|
|
|
+ if lastDateT.Before(endT) {
|
|
|
+ //如果最新的日期在起始日之前,则跳出循环
|
|
|
+ break
|
|
|
+ }
|
|
|
+ }
|
|
|
+ lenYear := len(dataMap)
|
|
|
+ for k, v := range dataMap {
|
|
|
+ if i, ok := chartLegendMap[k]; ok {
|
|
|
+ v.ChartLegend = strconv.Itoa(endYear - lenYear + i)
|
|
|
+ }
|
|
|
+ dataMap[k] = v
|
|
|
+ }
|
|
|
+
|
|
|
+ yearDataListMap := make(map[int]*data.EdbDataItems, 0)
|
|
|
+
|
|
|
+ for _, lv := range result.List {
|
|
|
+ yearDataListMap[lv.Year] = lv
|
|
|
+ }
|
|
|
+
|
|
|
+ //判断哪些点应该落在同一条时间线上
|
|
|
+ /*maxY := lastDateT.Year()
|
|
|
+ changeFlag := false
|
|
|
+ if lastDateT.Month() >= 11 {
|
|
|
+ maxY = maxY + 1
|
|
|
+ }
|
|
|
+ if maxY < nowYear {
|
|
|
+ changeFlag = true
|
|
|
+ maxY = nowYear
|
|
|
+ }*/
|
|
|
+ /*endTmp := fmt.Sprintf("%d-%s", maxY, xEndDate)
|
|
|
+ endTmpT, _ := time.Parse(utils.FormatDate, endTmp)
|
|
|
+ minY := maxY
|
|
|
+ if jumpYear == 1 {
|
|
|
+ minY = maxY - 1
|
|
|
+ }
|
|
|
+ startTmp := fmt.Sprintf("%d-%s", minY, xStartDate)
|
|
|
+ startTmpT, _ := time.Parse(utils.FormatDate, startTmp)*/
|
|
|
+
|
|
|
+ fmt.Println("横轴截取日" + startTmpT.Format(utils.FormatDate) + " " + endTmpT.Format(utils.FormatDate))
|
|
|
+ fmt.Printf("lastDateT.Year() 为%d \n", lastDateT.Year())
|
|
|
+ fmt.Printf("maxY 为%d \n", maxY)
|
|
|
+ for name, dateItem := range dataMap {
|
|
|
+ tY := dateItem.EndDate.Year()
|
|
|
+ if lastDateT.Month() >= 11 {
|
|
|
+ if maxY > endTmpT.Year() {
|
|
|
+ tY = tY + 1
|
|
|
+ }
|
|
|
+ }
|
|
|
+ lv, ok1 := yearDataListMap[tY]
|
|
|
+ fmt.Printf("name %s yearDataListMap[%d]\n", name, tY)
|
|
|
+ if !ok1 {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ for _, item := range lv.Items {
|
|
|
+ tmpVal := models.EdbDataList{
|
|
|
+ EdbDataId: item.EdbDataId,
|
|
|
+ EdbInfoId: item.EdbInfoId,
|
|
|
+ DataTime: item.DataTime,
|
|
|
+ DataTimestamp: item.DataTimestamp,
|
|
|
+ Value: item.Value,
|
|
|
+ }
|
|
|
+ dataTimeT, _ := time.Parse(utils.FormatDate, item.DataTime)
|
|
|
+ if (startTmpT.Before(dataTimeT) && endTmpT.After(dataTimeT)) || startTmpT == dataTimeT || endTmpT == dataTimeT {
|
|
|
+ tmpV := &tmpVal
|
|
|
+ if findVal, ok := quarterMap[name]; !ok {
|
|
|
+ findVal = append(findVal, tmpV)
|
|
|
+ quarterMap[name] = findVal
|
|
|
+ } else {
|
|
|
+ findVal = append(findVal, tmpV)
|
|
|
+ quarterMap[name] = findVal
|
|
|
+ }
|
|
|
+ if lv.Year >= latestDateYear {
|
|
|
+ // 切割的日期时间字符串
|
|
|
+ cuttingDataTimeStr := latestDate.AddDate(0, 0, lv.BetweenDay).Format(utils.FormatDate)
|
|
|
+ if item.DataTime == cuttingDataTimeStr {
|
|
|
+ dateItem.CuttingDataTimestamp = tmpVal.DataTimestamp
|
|
|
+ dataMap[name] = dateItem
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ for k, v := range dataMap {
|
|
|
+ itemList := quarterMap[k]
|
|
|
+ quarterItem := new(models.QuarterData)
|
|
|
+ quarterItem.Years = v.ShowName
|
|
|
+ quarterItem.ChartLegend = v.ChartLegend
|
|
|
+ if le, ok := legendMap[v.ShowName]; ok {
|
|
|
+ if le != strconv.Itoa(v.StartDate.Year()) && le != strconv.Itoa(v.EndDate.Year()) {
|
|
|
+ quarterItem.ChartLegend = le
|
|
|
+ }
|
|
|
+ }
|
|
|
+ quarterItem.DataList = itemList
|
|
|
+ quarterItem.CuttingDataTimestamp = v.CuttingDataTimestamp
|
|
|
+ //如果等于最后的实际日期,那么将切割时间戳记录
|
|
|
+ if quarterItem.CuttingDataTimestamp == 0 {
|
|
|
+ //如果大于最后的实际日期,那么第一个点就是切割的时间戳
|
|
|
+ if latestDate.Before(v.StartDate) && len(itemList) > 0 {
|
|
|
+ quarterItem.CuttingDataTimestamp = itemList[0].DataTimestamp - 100
|
|
|
+ }
|
|
|
+ }
|
|
|
+ quarterDataList = append(quarterDataList, quarterItem)
|
|
|
+ }
|
|
|
+
|
|
|
+ if result.List[0].Year != calendarPreYear {
|
|
|
+ itemList := make([]*models.EdbDataList, 0)
|
|
|
+ items := new(models.QuarterData)
|
|
|
+ //items.Year = calendarPreYear
|
|
|
+ items.DataList = itemList
|
|
|
+
|
|
|
+ newResult := make([]*models.QuarterData, 0)
|
|
|
+ newResult = append(newResult, items)
|
|
|
+ newResult = append(newResult, quarterDataList...)
|
|
|
+ resultData = newResult
|
|
|
+ } else {
|
|
|
+ resultData = quarterDataList
|
|
|
+ }
|
|
|
+
|
|
|
+ if len(quarterDataList) > 0 {
|
|
|
+ quarterDataListSort = resultData
|
|
|
+ sort.Sort(quarterDataListSort)
|
|
|
+ }
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+// BarChartData 柱方图的数据处理
|
|
|
+func BarChartData(mappingList []*models.ChartEdbInfoMapping, edbDataListMap map[int][]*models.EdbDataList, barChartInfoDateList []models.BarChartInfoDateReq, barChartInfoSort models.BarChartInfoSortReq) (edbIdList []int, yDataList []models.YData, err error) {
|
|
|
+ // 指标数据数组(10086:{"2022-12-02":100.01,"2022-12-01":102.3})
|
|
|
+ edbDataMap := make(map[int]map[string]float64)
|
|
|
+ for edbInfoId, edbDataList := range edbDataListMap {
|
|
|
+ edbDateData := make(map[string]float64)
|
|
|
+ for _, edbData := range edbDataList {
|
|
|
+ edbDateData[edbData.DataTime] = edbData.Value
|
|
|
+ }
|
|
|
+ edbDataMap[edbInfoId] = edbDateData
|
|
|
+ }
|
|
|
+
|
|
|
+ // edbIdList 指标展示顺序;x轴的指标顺序
|
|
|
+ edbIdList = make([]int, 0)
|
|
|
+ //Sort int `description:"排序类型,0:默认,1:升序,2:降序"`
|
|
|
+ dateData := make(map[int]float64)
|
|
|
+ if barChartInfoSort.Sort == 0 {
|
|
|
+ for _, v := range mappingList {
|
|
|
+ edbIdList = append(edbIdList, v.EdbInfoId)
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ lenBarChartInfoDateList := len(barChartInfoDateList)
|
|
|
+ if barChartInfoSort.DateIndex >= lenBarChartInfoDateList {
|
|
|
+ err = errors.New("排序日期异常")
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ notDataEdbIdList := make([]int, 0) //没有数据的指标id
|
|
|
+ // 日期配置
|
|
|
+ barChartInfoDate := barChartInfoDateList[barChartInfoSort.DateIndex]
|
|
|
+ for edbInfoId, dataList := range edbDataListMap {
|
|
|
+ if len(dataList) <= 0 {
|
|
|
+ // 没有数据的指标id
|
|
|
+ notDataEdbIdList = append(notDataEdbIdList, edbInfoId)
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ findDate := barChartInfoDate.Date
|
|
|
+ switch barChartInfoDate.Type {
|
|
|
+ case 1: //最新值
|
|
|
+ findDate = dataList[len(dataList)-1].DataTime
|
|
|
+ case 2: //近期几天
|
|
|
+ findDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, dataList[len(dataList)-1].DataTime, time.Local)
|
|
|
+ if tmpErr != nil {
|
|
|
+ err = tmpErr
|
|
|
+ return
|
|
|
+ }
|
|
|
+ findDateTime = findDateTime.AddDate(0, 0, -barChartInfoDate.Value)
|
|
|
+
|
|
|
+ lenData := len(dataList) - 1
|
|
|
+
|
|
|
+ for i := lenData; i >= 0; i-- {
|
|
|
+ currDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, dataList[i].DataTime, time.Local)
|
|
|
+ if tmpErr != nil {
|
|
|
+ err = tmpErr
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if currDateTime.Equal(findDateTime) || currDateTime.Before(findDateTime) {
|
|
|
+ findDate = dataList[i].DataTime
|
|
|
+ break
|
|
|
+ }
|
|
|
+ }
|
|
|
+ case 3: // 固定日期
|
|
|
+ //最早的日期
|
|
|
+ minDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, dataList[0].DataTime, time.Local)
|
|
|
+ if tmpErr != nil {
|
|
|
+ err = tmpErr
|
|
|
+ return
|
|
|
+ }
|
|
|
+ //寻找固定日期的数据
|
|
|
+ findDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, barChartInfoDate.Date, time.Local)
|
|
|
+ if tmpErr != nil {
|
|
|
+ err = tmpErr
|
|
|
+ return
|
|
|
+ }
|
|
|
+ for tmpDateTime := findDateTime; tmpDateTime.After(minDateTime) || tmpDateTime.Equal(minDateTime); tmpDateTime = tmpDateTime.AddDate(0, 0, -1) {
|
|
|
+ tmpDate := tmpDateTime.Format(utils.FormatDate)
|
|
|
+ if _, ok := edbDataMap[edbInfoId][tmpDate]; ok { //如果能找到数据,那么就返回
|
|
|
+ findDate = tmpDate
|
|
|
+ break
|
|
|
+ }
|
|
|
+ }
|
|
|
+ default:
|
|
|
+ err = errors.New(fmt.Sprint("日期类型异常,Type:", barChartInfoDate.Type))
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if tmpValue, ok := edbDataMap[edbInfoId][findDate]; ok {
|
|
|
+ dateData[edbInfoId] = tmpValue
|
|
|
+ } else {
|
|
|
+ // 没有数据的指标id
|
|
|
+ notDataEdbIdList = append(notDataEdbIdList, edbInfoId)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //Sort int `description:"排序类型,0:默认,1:升序,2:降序"`
|
|
|
+ // 排序
|
|
|
+ dateDataSort := utils.NewMapSorter(dateData)
|
|
|
+ sort.Sort(dateDataSort)
|
|
|
+ if barChartInfoSort.Sort == 1 {
|
|
|
+ // 先将没有数据的指标id放在最前面
|
|
|
+ if len(notDataEdbIdList) > 0 {
|
|
|
+ edbIdList = append(edbIdList, notDataEdbIdList...)
|
|
|
+ }
|
|
|
+ for _, v := range dateDataSort {
|
|
|
+ edbIdList = append(edbIdList, v.Key)
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ for i := len(dateDataSort) - 1; i >= 0; i-- {
|
|
|
+ edbIdList = append(edbIdList, dateDataSort[i].Key)
|
|
|
+ }
|
|
|
+ // 再将没有数据的指标id放在最后面
|
|
|
+ if len(notDataEdbIdList) > 0 {
|
|
|
+ edbIdList = append(edbIdList, notDataEdbIdList...)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ yDataList = make([]models.YData, 0) //y轴的数据列表
|
|
|
+
|
|
|
+ for _, barChartInfoDate := range barChartInfoDateList {
|
|
|
+ var maxDate time.Time
|
|
|
+
|
|
|
+ findDataList := make([]float64, 0) // 当前日期的数据值
|
|
|
+ for _, edbInfoId := range edbIdList {
|
|
|
+ findDate := barChartInfoDate.Date //需要的日期值
|
|
|
+ dataList := edbDataListMap[edbInfoId] //指标的所有数据值
|
|
|
+ if len(dataList) <= 0 {
|
|
|
+ // 没有数据的指标id
|
|
|
+ findDataList = append(findDataList, 0)
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ switch barChartInfoDate.Type {
|
|
|
+ case 1: //最新值
|
|
|
+ dataList := edbDataListMap[edbInfoId]
|
|
|
+ findDate = dataList[len(dataList)-1].DataTime
|
|
|
+ case 2: //近期几天
|
|
|
+ findDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, dataList[len(dataList)-1].DataTime, time.Local)
|
|
|
+ if tmpErr != nil {
|
|
|
+ err = tmpErr
|
|
|
+ return
|
|
|
+ }
|
|
|
+ findDateTime = findDateTime.AddDate(0, 0, -barChartInfoDate.Value)
|
|
|
+
|
|
|
+ lenData := len(dataList) - 1
|
|
|
+ for i := lenData; i >= 0; i-- {
|
|
|
+ currDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, dataList[i].DataTime, time.Local)
|
|
|
+ if tmpErr != nil {
|
|
|
+ err = tmpErr
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if currDateTime.Equal(findDateTime) || currDateTime.Before(findDateTime) {
|
|
|
+ findDate = dataList[i].DataTime
|
|
|
+ break
|
|
|
+ }
|
|
|
+ }
|
|
|
+ case 3: // 固定日期
|
|
|
+ //最早的日期
|
|
|
+ minDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, dataList[0].DataTime, time.Local)
|
|
|
+ if tmpErr != nil {
|
|
|
+ err = tmpErr
|
|
|
+ return
|
|
|
+ }
|
|
|
+ //寻找固定日期的数据
|
|
|
+ findDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, barChartInfoDate.Date, time.Local)
|
|
|
+ if tmpErr != nil {
|
|
|
+ err = tmpErr
|
|
|
+ return
|
|
|
+ }
|
|
|
+ for tmpDateTime := findDateTime; tmpDateTime.After(minDateTime) || tmpDateTime.Equal(minDateTime); tmpDateTime = tmpDateTime.AddDate(0, 0, -1) {
|
|
|
+ tmpDate := tmpDateTime.Format(utils.FormatDate)
|
|
|
+ if _, ok := edbDataMap[edbInfoId][tmpDate]; ok { //如果能找到数据,那么就返回
|
|
|
+ findDate = tmpDate
|
|
|
+ break
|
|
|
+ }
|
|
|
+ }
|
|
|
+ default:
|
|
|
+ err = errors.New(fmt.Sprint("日期类型异常,Type:", barChartInfoDate.Type))
|
|
|
+ return
|
|
|
+ }
|
|
|
+ findDateTime, _ := time.ParseInLocation(utils.FormatDate, findDate, time.Local)
|
|
|
+ if maxDate.IsZero() {
|
|
|
+ maxDate = findDateTime
|
|
|
+ } else {
|
|
|
+ if findDateTime.After(maxDate) {
|
|
|
+ maxDate = findDateTime
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if tmpValue, ok := edbDataMap[edbInfoId][findDate]; ok {
|
|
|
+ tmpValue, _ = decimal.NewFromFloat(tmpValue).Round(4).Float64()
|
|
|
+ findDataList = append(findDataList, tmpValue)
|
|
|
+ } else {
|
|
|
+ findDataList = append(findDataList, 0)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ yDate := "0000-00-00"
|
|
|
+ if !maxDate.IsZero() {
|
|
|
+ yDate = maxDate.Format(utils.FormatDate)
|
|
|
+ }
|
|
|
+ yDataList = append(yDataList, models.YData{
|
|
|
+ Date: yDate,
|
|
|
+ Value: findDataList,
|
|
|
+ Color: barChartInfoDate.Color,
|
|
|
+ Name: barChartInfoDate.Name,
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+func CheckIsEnChart(chartNameEn string, edbList []*models.ChartEdbInfoMapping, source, chartType int) bool {
|
|
|
+ // 相关性图表不判断指标
|
|
|
+ if utils.InArrayByInt([]int{utils.CHART_SOURCE_CORRELATION, utils.CHART_SOURCE_ROLLING_CORRELATION, utils.CHART_SOURCE_LINE_EQUATION}, source) && chartNameEn != "" {
|
|
|
+ return true
|
|
|
+ }
|
|
|
+ if chartNameEn != "" && len(edbList) <= 0 {
|
|
|
+ return true
|
|
|
+ }
|
|
|
+ if chartNameEn == "" {
|
|
|
+ return false
|
|
|
+ }
|
|
|
+
|
|
|
+ // 截面散点图的话,肯定是有英文配置的
|
|
|
+ if chartType == utils.CHART_TYPE_SECTION_SCATTER {
|
|
|
+ return true
|
|
|
+ }
|
|
|
+
|
|
|
+ for _, v := range edbList {
|
|
|
+ if v.EdbNameEn == "" {
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ if v.Unit != "无" && v.Unit != "" && v.UnitEn == "" {
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return true
|
|
|
+}
|
|
|
+
|
|
|
+func CheckIsEnEdb(edbNameEn, unit, unitEn string) bool {
|
|
|
+ if edbNameEn == "" {
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ if unit != "无" && unit != "" && unitEn == "" {
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ return true
|
|
|
+}
|
|
|
+
|
|
|
+// CheckChartExtraConfig 校验图表额外配置的信息,并且获取相关联的指标id
|
|
|
+func CheckChartExtraConfig(chartType int, extraConfigStr string) (edbIdList []int, err error, errMsg string) {
|
|
|
+ switch chartType {
|
|
|
+ case 10: //截面散点
|
|
|
+ var extraConfig models.SectionScatterReq
|
|
|
+ err = json.Unmarshal([]byte(extraConfigStr), &extraConfig)
|
|
|
+ if err != nil {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 判断是否有配置日期序列
|
|
|
+ if len(extraConfig.SeriesList) <= 0 {
|
|
|
+ errMsg = `请配置序列`
|
|
|
+ err = errors.New(errMsg)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 判断是否有填写指标
|
|
|
+ if len(extraConfig.SeriesList[0].EdbInfoList) <= 0 {
|
|
|
+ errMsg = `请选择指标`
|
|
|
+ err = errors.New(errMsg)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 遍历指标列表获取指标id
|
|
|
+ edbIdMap := make(map[int]int)
|
|
|
+ for _, v := range extraConfig.SeriesList[0].EdbInfoList {
|
|
|
+ // X 轴的指标id
|
|
|
+ if _, ok := edbIdMap[v.XEdbInfoId]; !ok {
|
|
|
+ edbIdMap[v.XEdbInfoId] = v.XEdbInfoId
|
|
|
+ edbIdList = append(edbIdList, v.XEdbInfoId)
|
|
|
+ }
|
|
|
+
|
|
|
+ // Y 轴的指标id
|
|
|
+ if _, ok := edbIdMap[v.YEdbInfoId]; !ok {
|
|
|
+ edbIdMap[v.YEdbInfoId] = v.YEdbInfoId
|
|
|
+ edbIdList = append(edbIdList, v.YEdbInfoId)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ case utils.CHART_TYPE_RADAR:
|
|
|
+ var extraConfig models.RadarChartInfoReq
|
|
|
+ if extraConfigStr == `` {
|
|
|
+ errMsg = "雷达图未配置"
|
|
|
+ err = errors.New(errMsg)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ err = json.Unmarshal([]byte(extraConfigStr), &extraConfig)
|
|
|
+ if err != nil {
|
|
|
+ errMsg = "雷达图配置异常"
|
|
|
+ err = errors.New(errMsg)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+// GetSectionScatterChartData 截面散点图的数据处理
|
|
|
+func GetSectionScatterChartData(chartInfoId int, mappingList []*models.ChartEdbInfoMapping, edbDataListMap map[int][]*models.EdbDataList, extraConfig models.SectionScatterReq) (edbIdList []int, chartDataResp models.SectionScatterInfoResp, 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
|
|
|
+ }
|
|
|
+ //SectionScatterSeriesInfoResp
|
|
|
+
|
|
|
+ dataListResp := make([]models.SectionScatterSeriesItemResp, 0) //y轴的数据列表
|
|
|
+
|
|
|
+ for _, seriesItem := range extraConfig.SeriesList {
|
|
|
+ var maxDate time.Time
|
|
|
+ // 系列中的指标数据
|
|
|
+ tmpSeriesEdbInfoList := make([]models.SectionScatterEdbItemResp, 0)
|
|
|
+
|
|
|
+ var minXVal, maxXVal, minYVal, maxYVal float64
|
|
|
+ for _, edbConf := range seriesItem.EdbInfoList {
|
|
|
+ tmpItem := models.SectionScatterEdbItemResp{
|
|
|
+ IsShow: edbConf.IsShow,
|
|
|
+ Name: edbConf.Name,
|
|
|
+ NameEn: edbConf.NameEn,
|
|
|
+ } //单个坐标点的数据
|
|
|
+
|
|
|
+ //X轴的数据
|
|
|
+ {
|
|
|
+ edbInfoId := edbConf.XEdbInfoId //X轴的指标
|
|
|
+ edbMappingInfo, ok := edbMappingMap[edbInfoId]
|
|
|
+ if !ok {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ findDate := edbConf.XDate //需要的日期值
|
|
|
+ dataList := edbDataListMap[edbInfoId] //指标的所有数据值
|
|
|
+ if len(dataList) <= 0 {
|
|
|
+ // 没有数据的指标id
|
|
|
+ //findDataList = append(findDataList, 0)
|
|
|
+ continue
|
|
|
+ }
|
|
|
+
|
|
|
+ tmpItem.XEdbInfoId = edbInfoId
|
|
|
+ tmpItem.XName = edbMappingInfo.EdbName
|
|
|
+ tmpItem.XNameEn = edbMappingInfo.EdbNameEn
|
|
|
+
|
|
|
+ switch edbConf.XDateType {
|
|
|
+ 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, -edbConf.XDateValue)
|
|
|
+
|
|
|
+ lenData := len(dataList) - 1
|
|
|
+ for i := lenData; i >= 0; i-- {
|
|
|
+ currDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, dataList[i].DataTime, time.Local)
|
|
|
+ if tmpErr != nil {
|
|
|
+ err = tmpErr
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if currDateTime.Equal(findDateTime) || currDateTime.Before(findDateTime) {
|
|
|
+ findDate = dataList[i].DataTime
|
|
|
+ break
|
|
|
+ }
|
|
|
+ }
|
|
|
+ case 3: // 固定日期
|
|
|
+ //最早的日期
|
|
|
+ minDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, dataList[0].DataTime, time.Local)
|
|
|
+ if tmpErr != nil {
|
|
|
+ err = tmpErr
|
|
|
+ return
|
|
|
+ }
|
|
|
+ //寻找固定日期的数据
|
|
|
+ findDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, edbConf.XDate, time.Local)
|
|
|
+ if tmpErr != nil {
|
|
|
+ err = tmpErr
|
|
|
+ return
|
|
|
+ }
|
|
|
+ for tmpDateTime := findDateTime; tmpDateTime.After(minDateTime) || tmpDateTime.Equal(minDateTime); tmpDateTime = tmpDateTime.AddDate(0, 0, -1) {
|
|
|
+ tmpDate := tmpDateTime.Format(utils.FormatDate)
|
|
|
+ if _, ok := edbDataMap[edbInfoId][tmpDate]; ok { //如果能找到数据,那么就返回
|
|
|
+ findDate = tmpDate
|
|
|
+ break
|
|
|
+ }
|
|
|
+ }
|
|
|
+ default:
|
|
|
+ err = errors.New(fmt.Sprint("日期类型异常,Type:", edbConf.XDate))
|
|
|
+ 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 {
|
|
|
+ tmpItem.XDate = findDate
|
|
|
+ tmpItem.XValue = tmpValue
|
|
|
+ } else {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //Y轴的数据
|
|
|
+ {
|
|
|
+ edbInfoId := edbConf.YEdbInfoId //Y轴的指标
|
|
|
+ edbMappingInfo, ok := edbMappingMap[edbInfoId]
|
|
|
+ if !ok {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ findDate := edbConf.YDate //需要的日期值
|
|
|
+ dataList := edbDataListMap[edbInfoId] //指标的所有数据值
|
|
|
+ if len(dataList) <= 0 {
|
|
|
+ // 没有数据的指标id
|
|
|
+ //findDataList = append(findDataList, 0)
|
|
|
+ continue
|
|
|
+ }
|
|
|
+
|
|
|
+ tmpItem.YEdbInfoId = edbInfoId
|
|
|
+ tmpItem.YName = edbMappingInfo.EdbName
|
|
|
+ tmpItem.YNameEn = edbMappingInfo.EdbNameEn
|
|
|
+
|
|
|
+ switch edbConf.YDateType {
|
|
|
+ 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, -edbConf.YDateValue)
|
|
|
+
|
|
|
+ lenData := len(dataList) - 1
|
|
|
+ for i := lenData; i >= 0; i-- {
|
|
|
+ currDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, dataList[i].DataTime, time.Local)
|
|
|
+ if tmpErr != nil {
|
|
|
+ err = tmpErr
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if currDateTime.Equal(findDateTime) || currDateTime.Before(findDateTime) {
|
|
|
+ findDate = dataList[i].DataTime
|
|
|
+ break
|
|
|
+ }
|
|
|
+ }
|
|
|
+ case 3: // 固定日期
|
|
|
+ //最早的日期
|
|
|
+ minDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, dataList[0].DataTime, time.Local)
|
|
|
+ if tmpErr != nil {
|
|
|
+ err = tmpErr
|
|
|
+ return
|
|
|
+ }
|
|
|
+ //寻找固定日期的数据
|
|
|
+ findDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, edbConf.YDate, time.Local)
|
|
|
+ if tmpErr != nil {
|
|
|
+ err = tmpErr
|
|
|
+ return
|
|
|
+ }
|
|
|
+ for tmpDateTime := findDateTime; tmpDateTime.After(minDateTime) || tmpDateTime.Equal(minDateTime); tmpDateTime = tmpDateTime.AddDate(0, 0, -1) {
|
|
|
+ tmpDate := tmpDateTime.Format(utils.FormatDate)
|
|
|
+ if _, ok := edbDataMap[edbInfoId][tmpDate]; ok { //如果能找到数据,那么就返回
|
|
|
+ findDate = tmpDate
|
|
|
+ break
|
|
|
+ }
|
|
|
+ }
|
|
|
+ default:
|
|
|
+ err = errors.New(fmt.Sprint("日期类型异常,Type:", edbConf.YDate))
|
|
|
+ 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 {
|
|
|
+ tmpItem.YDate = findDate
|
|
|
+ tmpItem.YValue = tmpValue
|
|
|
+ } else {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取当前系列的X轴的最大最小值
|
|
|
+ {
|
|
|
+ if tmpItem.XValue < minXVal {
|
|
|
+ minXVal = tmpItem.XValue
|
|
|
+ }
|
|
|
+ if tmpItem.XValue > maxXVal {
|
|
|
+ maxXVal = tmpItem.XValue
|
|
|
+ }
|
|
|
+ if tmpItem.YValue < minYVal {
|
|
|
+ minYVal = tmpItem.YValue
|
|
|
+ }
|
|
|
+ if tmpItem.YValue > maxYVal {
|
|
|
+ maxYVal = tmpItem.YValue
|
|
|
+ }
|
|
|
+ }
|
|
|
+ tmpSeriesEdbInfoList = append(tmpSeriesEdbInfoList, tmpItem)
|
|
|
+ }
|
|
|
+
|
|
|
+ trendLimitData := make([]models.CoordinatePoint, 0) //趋势线的前后坐标点
|
|
|
+ var trendLine, rSquare string
|
|
|
+ // 生成线性方程式
|
|
|
+ var a, b float64
|
|
|
+ {
|
|
|
+ coordinateData := make([]utils.Coordinate, 0)
|
|
|
+ for _, tmpSeriesEdbInfo := range tmpSeriesEdbInfoList {
|
|
|
+ tmpCoordinate1 := utils.Coordinate{
|
|
|
+ X: tmpSeriesEdbInfo.XValue,
|
|
|
+ Y: tmpSeriesEdbInfo.YValue,
|
|
|
+ }
|
|
|
+ coordinateData = append(coordinateData, tmpCoordinate1)
|
|
|
+ }
|
|
|
+
|
|
|
+ // 只有存在两个坐标点的时候,才能去计算线性方程和R平方
|
|
|
+ if len(coordinateData) >= 2 {
|
|
|
+ a, b = utils.GetLinearResult(coordinateData)
|
|
|
+ if !math.IsNaN(a) && !math.IsNaN(b) {
|
|
|
+ if b > 0 {
|
|
|
+ trendLine = fmt.Sprintf("y=%sx+%s", utils.SubFloatToString(a, 4), utils.SubFloatToString(b, 4))
|
|
|
+ } else {
|
|
|
+ trendLine = fmt.Sprintf("y=%sx%s", utils.SubFloatToString(a, 4), utils.SubFloatToString(b, 4))
|
|
|
+ }
|
|
|
+
|
|
|
+ minYVal, _ = decimal.NewFromFloat(a).Mul(decimal.NewFromFloat(minXVal)).Add(decimal.NewFromFloat(b)).Round(4).Float64()
|
|
|
+ maxYVal, _ = decimal.NewFromFloat(a).Mul(decimal.NewFromFloat(maxXVal)).Add(decimal.NewFromFloat(b)).Round(4).Float64()
|
|
|
+ }
|
|
|
+
|
|
|
+ // 计算R平方
|
|
|
+ rSquare = fmt.Sprint(utils.CalculationDecisive(coordinateData))
|
|
|
+ }
|
|
|
+
|
|
|
+ trendLimitData = append(trendLimitData, models.CoordinatePoint{
|
|
|
+ X: minXVal,
|
|
|
+ Y: minYVal,
|
|
|
+ }, models.CoordinatePoint{
|
|
|
+ X: maxXVal,
|
|
|
+ Y: maxYVal,
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ dataListResp = append(dataListResp, models.SectionScatterSeriesItemResp{
|
|
|
+ Name: seriesItem.Name,
|
|
|
+ NameEn: seriesItem.NameEn,
|
|
|
+ IsNameDefault: seriesItem.IsNameDefault,
|
|
|
+ Color: seriesItem.Color,
|
|
|
+ EdbInfoList: tmpSeriesEdbInfoList,
|
|
|
+ ShowTrendLine: seriesItem.ShowTrendLine,
|
|
|
+ ShowFitEquation: seriesItem.ShowFitEquation,
|
|
|
+ ShowRSquare: seriesItem.ShowRSquare,
|
|
|
+ TrendLine: trendLine,
|
|
|
+ RSquare: rSquare,
|
|
|
+ TrendLimitData: trendLimitData,
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ // 截面散点图点击详情时自动更新系列名
|
|
|
+ if len(extraConfig.SeriesList) > 0 {
|
|
|
+ // 默认名字的时候才自动更新
|
|
|
+ if extraConfig.SeriesList[0].IsNameDefault {
|
|
|
+ firstXEdbInfoId := extraConfig.SeriesList[0].EdbInfoList[0].XEdbInfoId
|
|
|
+ needUpdate := false
|
|
|
+ if v, ok := edbMappingMap[firstXEdbInfoId]; ok {
|
|
|
+ extraConfig.SeriesList[0].Name = v.LatestDate
|
|
|
+ extraConfig.SeriesList[0].NameEn = v.LatestDate
|
|
|
+ dataListResp[0].Name = v.LatestDate
|
|
|
+ dataListResp[0].NameEn = v.LatestDate
|
|
|
+ needUpdate = true
|
|
|
+ }
|
|
|
+
|
|
|
+ extraConfigByte, e := json.Marshal(extraConfig)
|
|
|
+ if e != nil {
|
|
|
+ errMsg := "截面散点系列更新异常"
|
|
|
+ err = errors.New(errMsg)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ extraConfigStr := string(extraConfigByte)
|
|
|
+
|
|
|
+ if needUpdate {
|
|
|
+ err = models.EditChartInfoExtraConfig(chartInfoId, extraConfigStr)
|
|
|
+ if err != nil {
|
|
|
+ errMsg := "截面散点系列更新异常"
|
|
|
+ err = errors.New(errMsg)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ chartDataResp = models.SectionScatterInfoResp{
|
|
|
+ XName: extraConfig.XName,
|
|
|
+ XNameEn: extraConfig.XNameEn,
|
|
|
+ XUnitName: extraConfig.XUnitName,
|
|
|
+ XUnitNameEn: extraConfig.XUnitNameEn,
|
|
|
+ YName: extraConfig.YName,
|
|
|
+ YNameEn: extraConfig.YNameEn,
|
|
|
+ YUnitName: extraConfig.YUnitName,
|
|
|
+ YUnitNameEn: extraConfig.YUnitNameEn,
|
|
|
+ XMinValue: extraConfig.XMinValue,
|
|
|
+ XMaxValue: extraConfig.XMaxValue,
|
|
|
+ YMinValue: extraConfig.YMinValue,
|
|
|
+ YMaxValue: extraConfig.YMaxValue,
|
|
|
+ DataList: dataListResp,
|
|
|
+ }
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+// GetEdbSourceByEdbInfoIdList 获取关联指标的来源
|
|
|
+func GetEdbSourceByEdbInfoIdList(chartEdbInfoMappingList []*models.ChartEdbInfoMapping) (sourceNameList, sourceNameEnList []string) {
|
|
|
+ sourceNameList = make([]string, 0)
|
|
|
+ sourceNameEnList = make([]string, 0)
|
|
|
+ sourceMap := make(map[int]string)
|
|
|
+ for _, v := range chartEdbInfoMappingList {
|
|
|
+ // 指标类型:1:基础指标,2:计算指标
|
|
|
+ if v.EdbType == 2 || v.EdbInfoCategoryType == 1 {
|
|
|
+ //sourceMap[0] = "弘则研究"
|
|
|
+ baseEdbInfoArr, _, _ := GetRefreshEdbInfoFromBase(v.EdbInfoId, v.Source)
|
|
|
+ for _, baseEdbInfo := range baseEdbInfoArr {
|
|
|
+ if baseEdbInfo.EdbInfoType == 0 { //普通指标才参与,预测指标不参与
|
|
|
+ sourceMap[baseEdbInfo.Source] = baseEdbInfo.SourceName
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ sourceMap[v.Source] = v.SourceName
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ for source, sourceName := range sourceMap {
|
|
|
+ if utils.InArrayByInt([]int{utils.DATA_SOURCE_MANUAL, utils.DATA_SOURCE_MYSTEEL_CHEMICAL}, source) {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ sourceNameList = append(sourceNameList, sourceName)
|
|
|
+
|
|
|
+ sourceNameEn, ok := utils.DataSourceEnMap[source]
|
|
|
+ if !ok {
|
|
|
+ sourceNameEn = sourceName
|
|
|
+ }
|
|
|
+ sourceNameEnList = append(sourceNameEnList, sourceNameEn)
|
|
|
+ }
|
|
|
+ //sourceNameList = append(sourceNameList, utils.ChartDefaultNameCn)
|
|
|
+ //sourceNameEnList = append(sourceNameEnList, utils.ChartDefaultNameEn)
|
|
|
+
|
|
|
+ // 图表来源
|
|
|
+ /*conf, e := models.GetBusinessConf()
|
|
|
+ if e != nil {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if conf[models.BusinessConfCompanyName] != "" {
|
|
|
+ sourceNameList = append(sourceNameList, conf[models.BusinessConfCompanyName])
|
|
|
+ sourceNameEnList = append(sourceNameEnList, conf[models.BusinessConfCompanyName])
|
|
|
+ }*/
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+// RadarChartData 雷达图的数据处理
|
|
|
+func RadarChartData(mappingList []*models.ChartEdbInfoMapping, edbDataListMap map[int][]*models.EdbDataList, extraConfig models.RadarChartInfoReq) (edbIdList []int, chartDataResp models.RadarChartInfoResp, 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)
|
|
|
+ for _, v := range mappingList {
|
|
|
+ edbIdList = append(edbIdList, v.EdbInfoId)
|
|
|
+ }
|
|
|
+ chartDateList := extraConfig.DateList
|
|
|
+
|
|
|
+ yDataList := make([]models.RadarYData, 0) //y轴的数据列表
|
|
|
+
|
|
|
+ for _, chartDate := range chartDateList {
|
|
|
+ var maxDate time.Time
|
|
|
+
|
|
|
+ findDataList := make([]float64, 0) // 当前日期的数据值
|
|
|
+ for _, edbInfoId := range edbIdList {
|
|
|
+ findDate := chartDate.Date //需要的日期值
|
|
|
+ dataList := edbDataListMap[edbInfoId] //指标的所有数据值
|
|
|
+ if len(dataList) <= 0 {
|
|
|
+ // 没有数据的指标id
|
|
|
+ findDataList = append(findDataList, 0)
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ switch chartDate.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, -chartDate.Value)
|
|
|
+
|
|
|
+ lenData := len(dataList) - 1
|
|
|
+ for i := lenData; i >= 0; i-- {
|
|
|
+ currDateTime, e := time.ParseInLocation(utils.FormatDate, dataList[i].DataTime, time.Local)
|
|
|
+ if e != nil {
|
|
|
+ err = e
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if currDateTime.Equal(findDateTime) || currDateTime.Before(findDateTime) {
|
|
|
+ findDate = dataList[i].DataTime
|
|
|
+ break
|
|
|
+ }
|
|
|
+ }
|
|
|
+ case 3: // 固定日期
|
|
|
+ //最早的日期
|
|
|
+ minDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, dataList[0].DataTime, time.Local)
|
|
|
+ if tmpErr != nil {
|
|
|
+ err = tmpErr
|
|
|
+ return
|
|
|
+ }
|
|
|
+ //寻找固定日期的数据
|
|
|
+ findDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, chartDate.Date, time.Local)
|
|
|
+ if tmpErr != nil {
|
|
|
+ err = tmpErr
|
|
|
+ return
|
|
|
+ }
|
|
|
+ for tmpDateTime := findDateTime; tmpDateTime.After(minDateTime) || tmpDateTime.Equal(minDateTime); tmpDateTime = tmpDateTime.AddDate(0, 0, -1) {
|
|
|
+ tmpDate := tmpDateTime.Format(utils.FormatDate)
|
|
|
+ if _, ok := edbDataMap[edbInfoId][tmpDate]; ok { //如果能找到数据,那么就返回
|
|
|
+ findDate = tmpDate
|
|
|
+ break
|
|
|
+ }
|
|
|
+ }
|
|
|
+ default:
|
|
|
+ err = errors.New(fmt.Sprint("日期类型异常,Type:", chartDate.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 {
|
|
|
+ tmpValue, _ = decimal.NewFromFloat(tmpValue).Round(4).Float64()
|
|
|
+ findDataList = append(findDataList, tmpValue)
|
|
|
+ } else {
|
|
|
+ findDataList = append(findDataList, 0)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ yDate := "0000-00-00"
|
|
|
+ if !maxDate.IsZero() {
|
|
|
+ yDate = maxDate.Format(utils.FormatDate)
|
|
|
+ }
|
|
|
+ yDataList = append(yDataList, models.RadarYData{
|
|
|
+ Date: yDate,
|
|
|
+ Value: findDataList,
|
|
|
+ Color: chartDate.Color,
|
|
|
+ Name: chartDate.Name,
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ chartDataResp = models.RadarChartInfoResp{
|
|
|
+ YDataList: yDataList,
|
|
|
+ XEdbIdValue: edbIdList,
|
|
|
+ }
|
|
|
+ return
|
|
|
+}
|