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