|
@@ -66,6 +66,9 @@ type CoordinatePoint struct {
|
|
|
YEdbInfoId int
|
|
|
XDate string
|
|
|
YDate string
|
|
|
+ DateType int `description:"日期类型:1-最新日期;2-N天前;3-固定日期"`
|
|
|
+ DaysAgo int `description:"N天前的N值"`
|
|
|
+ ShowTips int `description:"是否显示标注:0-否;1-是"`
|
|
|
}
|
|
|
|
|
|
// GetChartData
|
|
@@ -161,7 +164,14 @@ func GetChartData(chartInfoId int, config request.ChartConfigReq) (edbList []*da
|
|
|
|
|
|
dataMap := make(map[string]float64)
|
|
|
dateMap := make(map[string]string)
|
|
|
+ dateTypeMap := make(map[int]int) // 日期配置key对应的日期类型
|
|
|
+ daysAgoMap := make(map[int]int) // 日期配置key对应的N天前的N值
|
|
|
+ showTipsMap := make(map[int]int) // 日期配置key对应点是否显示标注
|
|
|
+
|
|
|
for dateIndex, dateConfig := range config.DateConfigList {
|
|
|
+ dateTypeMap[dateIndex] = dateConfig.DateType
|
|
|
+ daysAgoMap[dateIndex] = dateConfig.Num
|
|
|
+ showTipsMap[dateIndex] = dateConfig.ShowTips
|
|
|
for _, edbInfoMapping := range mappingList {
|
|
|
// 数据会是正序的
|
|
|
dataList, ok := edbDataListMap[edbInfoMapping.EdbInfoId]
|
|
@@ -173,25 +183,28 @@ func GetChartData(chartInfoId int, config request.ChartConfigReq) (edbList []*da
|
|
|
if lenData <= 0 {
|
|
|
continue
|
|
|
}
|
|
|
+ // 数据的开始索引
|
|
|
+ k := lenData - 1
|
|
|
|
|
|
+ // 数据的最晚日期
|
|
|
+ dataEndDateStr := dataList[k].DataTime
|
|
|
+ dataEndDate, tmpErr := time.ParseInLocation(utils.FormatDate, dataEndDateStr, time.Local)
|
|
|
+ if tmpErr != nil {
|
|
|
+ err = tmpErr
|
|
|
+ return
|
|
|
+ }
|
|
|
// 数据开始日期
|
|
|
endDateStr := ``
|
|
|
var endDate time.Time
|
|
|
- // 数据的开始索引
|
|
|
- k := lenData - 1
|
|
|
+
|
|
|
var currVal float64
|
|
|
switch dateConfig.DateType {
|
|
|
case 1: // 1:最新日期;
|
|
|
- endDateStr = dataList[k].DataTime
|
|
|
- tmpDate, tmpErr := time.ParseInLocation(utils.FormatDate, endDateStr, time.Local)
|
|
|
- if tmpErr != nil {
|
|
|
- err = tmpErr
|
|
|
- return
|
|
|
- }
|
|
|
- endDate = tmpDate
|
|
|
+ endDateStr = dataEndDateStr
|
|
|
+ endDate = dataEndDate
|
|
|
currVal = dataList[k].Value
|
|
|
- case 2: // 2:N天前
|
|
|
- tmpEndDate := currDay.AddDate(0, 0, -dateConfig.Num)
|
|
|
+ case 2: // 2:N天前(原为指标最新日期的N天前, 现为系统日期的N天)
|
|
|
+ tmpEndDate := time.Now().AddDate(0, 0, -dateConfig.Num)
|
|
|
tmpEndDateStr := tmpEndDate.Format(utils.FormatDate)
|
|
|
|
|
|
for i := k; i >= 0; i-- {
|
|
@@ -200,6 +213,7 @@ func GetChartData(chartInfoId int, config request.ChartConfigReq) (edbList []*da
|
|
|
if tmpEndDateStr == tmpDateStr {
|
|
|
k = i
|
|
|
endDateStr = tmpDateStr
|
|
|
+ endDate = tmpEndDate
|
|
|
currVal = dataList[i].Value
|
|
|
break
|
|
|
}
|
|
@@ -218,6 +232,45 @@ func GetChartData(chartInfoId int, config request.ChartConfigReq) (edbList []*da
|
|
|
currVal = dataList[i].Value
|
|
|
break
|
|
|
}
|
|
|
+ case 3: // 固定日期
|
|
|
+ if dateConfig.FixDate == "" {
|
|
|
+ errMsg = "固定日期不可为空"
|
|
|
+ err = fmt.Errorf("固定日期为空")
|
|
|
+ return
|
|
|
+ }
|
|
|
+ strFixDate := dateConfig.FixDate
|
|
|
+ fixDate, e := time.ParseInLocation(utils.FormatDate, strFixDate, time.Local)
|
|
|
+ if e != nil {
|
|
|
+ errMsg = "固定日期格式有误"
|
|
|
+ err = fmt.Errorf("固定日期有误, FixDate: %s", dateConfig.FixDate)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ for i := k; i >= 0; i-- {
|
|
|
+ strThisDate := dataList[i].DataTime
|
|
|
+ // 如果正好是这一天,那么就直接break了
|
|
|
+ if strFixDate == strThisDate {
|
|
|
+ k = i
|
|
|
+ endDateStr = strThisDate
|
|
|
+ endDate = fixDate
|
|
|
+ currVal = dataList[i].Value
|
|
|
+ break
|
|
|
+ }
|
|
|
+ // 若固定日期无值, 则取固定日期之前, 能找到的第一个值(同上N天前的逻辑)
|
|
|
+ thisDate, e := time.ParseInLocation(utils.FormatDate, strThisDate, time.Local)
|
|
|
+ if e != nil {
|
|
|
+ err = fmt.Errorf("数据日期格式有误: %s", e.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if thisDate.After(fixDate) {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ k = i
|
|
|
+ endDateStr = strThisDate
|
|
|
+ endDate = thisDate
|
|
|
+ currVal = dataList[i].Value
|
|
|
+ break
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
// 没有找到日期,那么就不处理
|
|
@@ -229,51 +282,85 @@ func GetChartData(chartInfoId int, config request.ChartConfigReq) (edbList []*da
|
|
|
earliestDate := endDate.AddDate(0, 0, -config.CalculateValue*moveUnitDays)
|
|
|
earliestDateStr := earliestDate.Format(utils.FormatDate)
|
|
|
|
|
|
- var minVal, maxVal float64
|
|
|
- var isNotFirst bool // 是否是第一条数据
|
|
|
- for i := k; i >= 0; i-- {
|
|
|
- tmpData := dataList[i]
|
|
|
- if !isNotFirst {
|
|
|
- maxVal = tmpData.Value
|
|
|
- minVal = tmpData.Value
|
|
|
- isNotFirst = true
|
|
|
- continue
|
|
|
- }
|
|
|
+ var percentVal float64 // 百分位计算值
|
|
|
+ // 百分位数据区间算法
|
|
|
+ if config.PercentType == utils.PercentCalculateTypeRange {
|
|
|
+ var minVal, maxVal float64
|
|
|
+ var isNotFirst bool // 是否是第一条数据
|
|
|
+ for i := k; i >= 0; i-- {
|
|
|
+ tmpData := dataList[i]
|
|
|
+ if !isNotFirst {
|
|
|
+ maxVal = tmpData.Value
|
|
|
+ minVal = tmpData.Value
|
|
|
+ isNotFirst = true
|
|
|
+ continue
|
|
|
+ }
|
|
|
|
|
|
- tmpDateStr := dataList[i].DataTime
|
|
|
- // 如果正好是这一天,那么就直接break了
|
|
|
- if earliestDateStr == tmpDateStr {
|
|
|
- break
|
|
|
- }
|
|
|
- tmpDate, tmpErr := time.ParseInLocation(utils.FormatDate, tmpDateStr, time.Local)
|
|
|
- if tmpErr != nil {
|
|
|
- err = tmpErr
|
|
|
- return
|
|
|
+ tmpDateStr := dataList[i].DataTime
|
|
|
+ // 如果正好是这一天,那么就直接break了
|
|
|
+ if earliestDateStr == tmpDateStr {
|
|
|
+ break
|
|
|
+ }
|
|
|
+ tmpDate, tmpErr := time.ParseInLocation(utils.FormatDate, tmpDateStr, time.Local)
|
|
|
+ if tmpErr != nil {
|
|
|
+ err = tmpErr
|
|
|
+ return
|
|
|
+ }
|
|
|
+ // 如果这期的日期早于选择的日期,那么继续停止遍历
|
|
|
+ if tmpDate.Before(earliestDate) {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+
|
|
|
+ if tmpData.Value > maxVal {
|
|
|
+ maxVal = tmpData.Value
|
|
|
+ }
|
|
|
+ if tmpData.Value < minVal {
|
|
|
+ minVal = tmpData.Value
|
|
|
+ }
|
|
|
}
|
|
|
- // 如果这期的日期早于选择的日期,那么继续停止遍历
|
|
|
- if tmpDate.Before(earliestDate) {
|
|
|
+
|
|
|
+ // 最大值等于最小值,说明计算结果无效
|
|
|
+ if maxVal == minVal {
|
|
|
continue
|
|
|
}
|
|
|
+ // 数据区间百分位=(现值-Min)/(Max-Min)
|
|
|
+ tmpV := (currVal - minVal) / (maxVal - minVal) * 100
|
|
|
+ percentVal, _ = decimal.NewFromFloat(tmpV).Round(4).Float64()
|
|
|
+ }
|
|
|
|
|
|
- if tmpData.Value > maxVal {
|
|
|
- maxVal = tmpData.Value
|
|
|
+ // 百分位数据个数算法
|
|
|
+ // 数据区间第一个和最后一个数据点的时间和数据分别为(T1,S1)(T2,S2); N=T1到T2指标数据个数, n=小于等于S2的数据个数
|
|
|
+ // 个数百分位=(n-1)/(N-1)
|
|
|
+ if config.PercentType == utils.PercentCalculateTypeNum {
|
|
|
+ // T1为earliestDate, T2为endDate, S2为currVal
|
|
|
+ var tinyN, bigN int
|
|
|
+ lastVal := decimal.NewFromFloat(currVal)
|
|
|
+ for i := k; i >= 0; i-- {
|
|
|
+ date, e := time.ParseInLocation(utils.FormatDate, dataList[i].DataTime, time.Local)
|
|
|
+ if e != nil {
|
|
|
+ err = fmt.Errorf("数据日期格式有误: %s", e.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if !date.Before(earliestDate) && !date.After(endDate) {
|
|
|
+ bigN += 1
|
|
|
+ dateVal := decimal.NewFromFloat(dataList[i].Value)
|
|
|
+ if dateVal.LessThanOrEqual(lastVal) {
|
|
|
+ tinyN += 1
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
- if tmpData.Value < minVal {
|
|
|
- minVal = tmpData.Value
|
|
|
+ // N=1时说明计算无效
|
|
|
+ if bigN == 1 {
|
|
|
+ continue
|
|
|
}
|
|
|
+ numerator := decimal.NewFromInt(int64(tinyN - 1))
|
|
|
+ denominator := decimal.NewFromInt(int64(bigN - 1))
|
|
|
+ percentVal, _ = numerator.Div(denominator).Mul(decimal.NewFromFloat(100)).Round(4).Float64()
|
|
|
}
|
|
|
|
|
|
- // 最大值等于最小值,说明计算结果无效
|
|
|
- if maxVal == minVal {
|
|
|
- continue
|
|
|
- }
|
|
|
- //百分位=(现值-Min)/(Max-Min)
|
|
|
- tmpV := (currVal - minVal) / (maxVal - minVal) * 100
|
|
|
- tmpV, _ = decimal.NewFromFloat(tmpV).Round(4).Float64()
|
|
|
-
|
|
|
// key的生成(日期配置下标+指标id)
|
|
|
key := fmt.Sprint(dateIndex, "_", edbInfoMapping.EdbInfoId)
|
|
|
- dataMap[key] = tmpV
|
|
|
+ dataMap[key] = percentVal
|
|
|
dateMap[key] = endDateStr
|
|
|
}
|
|
|
}
|
|
@@ -337,6 +424,9 @@ func GetChartData(chartInfoId int, config request.ChartConfigReq) (edbList []*da
|
|
|
YEdbInfoId: yEdbInfoId,
|
|
|
XDate: dateMap[key1],
|
|
|
YDate: dateMap[key2],
|
|
|
+ DateType: dateTypeMap[dateIndex], // 日期类型
|
|
|
+ DaysAgo: daysAgoMap[dateIndex], // N天前的N值
|
|
|
+ ShowTips: showTipsMap[dateIndex], // 是否显示标注
|
|
|
})
|
|
|
}
|
|
|
|
|
@@ -347,6 +437,7 @@ func GetChartData(chartInfoId int, config request.ChartConfigReq) (edbList []*da
|
|
|
CoordinatePointData: coordinatePointList,
|
|
|
})
|
|
|
}
|
|
|
+
|
|
|
// 处理颜色
|
|
|
colorMap := utils.GetColorMap()
|
|
|
for k, _ := range dataList {
|
|
@@ -507,6 +598,12 @@ func AddChartInfo(req request.AddChartReq, sysUser *system.Admin) (chartInfo *da
|
|
|
isSendEmail = false
|
|
|
return
|
|
|
}
|
|
|
+ if req.PercentType != utils.PercentCalculateTypeRange && req.PercentType != utils.PercentCalculateTypeNum {
|
|
|
+ errMsg = "请选择百分位"
|
|
|
+ err = errors.New(errMsg)
|
|
|
+ isSendEmail = false
|
|
|
+ return
|
|
|
+ }
|
|
|
// 品种配置
|
|
|
if len(req.VarietyList) < 0 {
|
|
|
errMsg = "请选择品种!"
|
|
@@ -543,6 +640,9 @@ func AddChartInfo(req request.AddChartReq, sysUser *system.Admin) (chartInfo *da
|
|
|
return
|
|
|
}
|
|
|
|
|
|
+ // 分类没有,需要创建新的分类,那么err置空
|
|
|
+ err = nil
|
|
|
+
|
|
|
timestamp := strconv.FormatInt(time.Now().UnixNano(), 10)
|
|
|
chartClassify = &data_manage.ChartClassify{
|
|
|
ChartClassifyId: 0,
|
|
@@ -558,6 +658,7 @@ func AddChartInfo(req request.AddChartReq, sysUser *system.Admin) (chartInfo *da
|
|
|
Sort: 0,
|
|
|
Source: source,
|
|
|
}
|
|
|
+ _, err = data_manage.AddChartClassify(chartClassify)
|
|
|
}
|
|
|
|
|
|
var chartInfoId int
|
|
@@ -586,6 +687,7 @@ func AddChartInfo(req request.AddChartReq, sysUser *system.Admin) (chartInfo *da
|
|
|
//chartInfo.ChartClassifyId = req.ChartClassifyId
|
|
|
chartInfo.SysUserId = sysUser.AdminId
|
|
|
chartInfo.SysUserRealName = sysUser.RealName
|
|
|
+ chartInfo.ChartImage = req.ChartImage
|
|
|
chartInfo.CreateTime = time.Now()
|
|
|
chartInfo.ModifyTime = time.Now()
|
|
|
chartInfo.IsSetName = 0
|
|
@@ -600,11 +702,19 @@ func AddChartInfo(req request.AddChartReq, sysUser *system.Admin) (chartInfo *da
|
|
|
//chartInfo.SeasonEndDate = req.EndDate
|
|
|
chartInfo.LeftMin = req.LeftMin
|
|
|
chartInfo.LeftMax = req.LeftMax
|
|
|
+ chartInfo.XMin = req.XMin
|
|
|
+ chartInfo.XMax = req.XMax
|
|
|
//chartInfo.RightMin = req.RightMin
|
|
|
//chartInfo.RightMax = req.RightMax
|
|
|
//chartInfo.Disabled = disableVal
|
|
|
chartInfo.Source = source
|
|
|
chartInfo.ExtraConfig = string(extraConfigByte)
|
|
|
+ chartInfo.ChartImage = req.ChartImage
|
|
|
+ chartInfo.ChartThemeId = req.ChartThemeId
|
|
|
+ chartInfo.SourcesFrom = req.SourcesFrom
|
|
|
+ chartInfo.Instructions = req.Instructions
|
|
|
+ chartInfo.MarkersLines = req.MarkersLines
|
|
|
+ chartInfo.MarkersAreas = req.MarkersAreas
|
|
|
|
|
|
// 图表品种
|
|
|
chartVarietyMappingList := make([]*cross_varietyModel.ChartVarietyMapping, 0)
|
|
@@ -708,6 +818,12 @@ func EditChartInfo(req request.EditChartReq, sysUser *system.Admin) (chartItem *
|
|
|
isSendEmail = false
|
|
|
return
|
|
|
}
|
|
|
+ if req.PercentType != utils.PercentCalculateTypeRange && req.PercentType != utils.PercentCalculateTypeNum {
|
|
|
+ errMsg = "请选择百分位"
|
|
|
+ err = errors.New(errMsg)
|
|
|
+ isSendEmail = false
|
|
|
+ return
|
|
|
+ }
|
|
|
// 品种配置
|
|
|
if len(req.VarietyList) < 0 {
|
|
|
errMsg = "请选择品种!"
|
|
@@ -767,7 +883,11 @@ func EditChartInfo(req request.EditChartReq, sysUser *system.Admin) (chartItem *
|
|
|
chartItem.ChartName = req.ChartName
|
|
|
chartItem.ExtraConfig = string(extraConfigByte)
|
|
|
chartItem.ModifyTime = time.Now()
|
|
|
- chartUpdateCols := []string{"ChartName", "ExtraConfig", "ModifyTime"}
|
|
|
+ chartItem.LeftMin = req.LeftMin
|
|
|
+ chartItem.LeftMax = req.LeftMax
|
|
|
+ chartItem.XMin = req.XMin
|
|
|
+ chartItem.XMax = req.XMax
|
|
|
+ chartUpdateCols := []string{"ChartName", "ExtraConfig", "ModifyTime", "LeftMin", "LeftMax", "XMin", "XMax"}
|
|
|
|
|
|
// 跨品种分析配置
|
|
|
chartInfoCrossVariety, err := cross_varietyModel.GetChartInfoCrossVarietyByChartInfoId(chartItem.ChartInfoId)
|