zwxi 8 місяців тому
батько
коміт
cfb937e3c3

+ 33 - 22
models/data_manage/chart_info.go

@@ -2,6 +2,7 @@ package data_manage
 
 import (
 	"errors"
+	"eta/eta_api/models/data_manage/excel/request"
 	"eta/eta_api/models/mgo"
 	"eta/eta_api/utils"
 	"fmt"
@@ -264,23 +265,33 @@ type EditChartInfoReq struct {
 }
 
 type MarkersLine struct {
-	Axis             int    `json:"axis" description:"1左轴 2右轴 3横轴"`
-	AxisName         string `json:"axisName" description:"轴的名称,例如'左轴'"`
-	MarkLineType     int    `json:"markLineType" description:"1:固定 2:指标计算"`
-	Value            string `json:"value" description:"连线指向的数值,例如'4000'"`
-	From             string `json:"from" description:"连线的起始点,可以为空"`
-	To               string `json:"to" description:"连线的结束点,可以为空"`
-	LineWidth        int    `json:"lineWidth" description:"连线的宽度"`
-	DashStyle        string `json:"dashStyle" description:"连线的虚线样式,例如'ShortDashDot'"`
-	Color            string `json:"color" description:"连线的颜色"`
-	Text             string `json:"text" description:"连线旁边显示的文本"`
-	TextPosition     string `json:"textPosition" description:"文本的显示位置,例如'bottom'"`
-	TextColor        string `json:"textColor" description:"文本颜色"`
-	TextFontSize     int    `json:"textFontSize" description:"文本的字号大小"`
-	IsShow           bool   `json:"isShow" description:"是否显示连线及文本"`
-	Calculation      int    `json:"calculation" description:"计算方式 1区间均值 2区间均值加N倍标准差 3区间个数分位 4区间数值分位"`
-	CalculationValue int    `json:"calculationValue" description:"计算方式对应的值 2就是几倍标准差 3就是分位值 4就是数值值·"`
+	Axis             int             `json:"axis" description:"1左轴 2右轴 3横轴"`
+	AxisName         string          `json:"axisName" description:"轴的名称,例如'左轴'"`
+	MarkLineType     int             `json:"markLineType" description:"1:固定 2:指标计算"`
+	Value            string          `json:"value" description:"连线指向的数值,例如'4000'"`
+	From             string          `json:"from" description:"连线的起始点,可以为空"`
+	To               string          `json:"to" description:"连线的结束点,可以为空"`
+	LineWidth        int             `json:"lineWidth" description:"连线的宽度"`
+	DashStyle        string          `json:"dashStyle" description:"连线的虚线样式,例如'ShortDashDot'"`
+	Color            string          `json:"color" description:"连线的颜色"`
+	Text             string          `json:"text" description:"连线旁边显示的文本"`
+	TextPosition     string          `json:"textPosition" description:"文本的显示位置,例如'bottom'"`
+	TextColor        string          `json:"textColor" description:"文本颜色"`
+	TextFontSize     int             `json:"textFontSize" description:"文本的字号大小"`
+	IsShow           bool            `json:"isShow" description:"是否显示连线及文本"`
+	Calculation      int             `json:"calculation" description:"计算方式 1区间均值 2区间均值加N倍标准差 3区间个数分位 4区间数值分位"`
+	CalculationValue int             `json:"calculationValue" description:"计算方式对应的值 2就是几倍标准差 3就是分位值 4就是数值值·"`
+	TimeIntervalType int             `json:"timeInterval" description:"时间区间 0跟随图表 1自定义"`
+	StartDate        MarkersLineTime `json:"startTime" description:"开始时间"`
+	EndDate          MarkersLineTime `json:"endTime" description:"结束时间"`
+}
+
+type MarkersLineTime struct {
+	TimeType int                       `json:"timeType" description:"时间类型 1固定 2动态"`
+	Date     string                    `json:"date" description:"日期"`
+	Conf     request.EdbDateChangeConf `json:"conf" description:"动态时间配置"`
 }
+
 type EditChartEnInfoReq struct {
 	ChartInfoId      int                       `description:"图表ID"`
 	ChartNameEn      string                    `description:"英文图表名称"`
@@ -1506,18 +1517,18 @@ type SamePeriodAverageData struct {
 
 // 自定义同期标准差
 type SamePeriodStandardDeviation struct {
-	Color    string `description:"颜色"`
-	Year     int    `description:"标准差取值范围"`
-	Legend   string `description:"图例名称"`
-	Multiple float64    `description:"标准差倍数"`
-	IsShow   bool   `description:"是否显示"`
+	Color    string  `description:"颜色"`
+	Year     int     `description:"标准差取值范围"`
+	Legend   string  `description:"图例名称"`
+	Multiple float64 `description:"标准差倍数"`
+	IsShow   bool    `description:"是否显示"`
 }
 
 type SamePeriodStandardDeviationResp struct {
 	Color    string              `description:"颜色"`
 	Year     int                 `description:"标准差取值范围"`
 	Legend   string              `description:"图例名称"`
-	Multiple float64                 `description:"标准差倍数"`
+	Multiple float64             `description:"标准差倍数"`
 	IsShow   bool                `description:"是否显示"`
 	List     []*MaxMinLimitsData `description:"自定义标准差列表"`
 }

+ 7 - 3
services/data/chart_info.go

@@ -3165,6 +3165,10 @@ func GetChartEdbDataV2(chartInfoId, chartType int, calendar, startDate, endDate
 
 	// 特殊图形数据处理
 	switch chartType {
+	case 2: // 季节性图
+		if seasonExtraConfig != "" {
+			dataResp, err = SeasonChartData(edbList, seasonExtraConfig)
+		}
 	case 7: // 柱形图
 		barChartConf := extraConfig.(data_manage.BarChartInfoReq)
 		xEdbIdValue, yDataList, err = BarChartData(mappingList, edbDataListMap, barChartConf.DateList, barChartConf.Sort)
@@ -3388,7 +3392,7 @@ func SeasonChartData(dataList []*data_manage.ChartEdbInfoMapping, seasonExtraCon
 		}
 
 		// 自定义同期标准差
-		//if seasonConfig.SamePeriodStandardDeviation.Year > 1 && seasonConfig.SamePeriodStandardDeviation.Multiple > 0 {
+		if seasonConfig.SamePeriodStandardDeviation.Year > 1 && seasonConfig.SamePeriodStandardDeviation.Multiple > 0 {
 			// 先算均值,再算标准差
 			handleDataMap := make(map[string]float64)
 			dataTimeMap := make(map[time.Time]time.Time)
@@ -3399,7 +3403,7 @@ func SeasonChartData(dataList []*data_manage.ChartEdbInfoMapping, seasonExtraCon
 			samePeriodStandardDeviationList := make([]*data_manage.MaxMinLimitsData, 0)
 			for i := len(quarterDataList) - 1 ; i > len(quarterDataList) - seasonConfig.SamePeriodAverage.Year-1 && i > 0; i-- {
 				// 插值成日度
-				dataTimeList, _, err = HandleDataByLinearRegressionToList(quarterDataList[i].DataList, handleDataMap)
+				dataTimeList, _, err = HandleDataByLinearRegressionToListV2(quarterDataList[i].DataList, handleDataMap)
 				if err != nil {
 					err = errors.New("插值处理数据异常, Err:" + err.Error())
 					return
@@ -3455,7 +3459,7 @@ func SeasonChartData(dataList []*data_manage.ChartEdbInfoMapping, seasonExtraCon
 			dataResp.SamePeriodStandardDeviation.IsShow = seasonConfig.SamePeriodStandardDeviation.IsShow
 			dataResp.SamePeriodStandardDeviation.Multiple = seasonConfig.SamePeriodStandardDeviation.Multiple
 			dataResp.SamePeriodStandardDeviation.Year = seasonConfig.SamePeriodStandardDeviation.Year
-		//}
+		}
 
 	}
 

+ 69 - 0
services/data/edb_info_calculate.go

@@ -9,6 +9,7 @@ import (
 	"github.com/shopspring/decimal"
 	"math"
 	"regexp"
+	"sort"
 	"strings"
 	"time"
 )
@@ -673,6 +674,7 @@ func HandleDataByLinearRegressionToList (edbInfoDataList []*data_manage.EdbDataL
 		// 第一个数据就给过滤了,给后面的试用
 		if startEdbInfoData == nil {
 			startEdbInfoData = v
+			//startEdbInfoData.DataTime = startEdbInfoData.DataTime[:5]+ "01-01"
 			continue
 		}
 
@@ -730,3 +732,70 @@ func HandleDataByLinearRegressionToList (edbInfoDataList []*data_manage.EdbDataL
 
 	return
 }
+
+// HandleDataByLinearRegressionToList 保证生成365个数据点的线性插值法
+func HandleDataByLinearRegressionToListV2(edbInfoDataList []*data_manage.EdbDataList, handleDataMap map[string]float64) (dataTimeList []string, valueList []float64, err error) {
+	if len(edbInfoDataList) < 2 {
+		return
+	}
+
+	// 确保至少有两天数据来生成线性方程
+	if len(edbInfoDataList) < 2 {
+		err = errors.New("至少需要两天的数据来执行线性插值")
+		return
+	}
+
+	// 对数据按日期排序,确保顺序正确
+	sort.Slice(edbInfoDataList, func(i, j int) bool {
+		t1, _ := time.ParseInLocation(utils.FormatDate, edbInfoDataList[i].DataTime, time.Local)
+		t2, _ := time.ParseInLocation(utils.FormatDate, edbInfoDataList[j].DataTime, time.Local)
+		return t1.Before(t2)
+	})
+
+	startEdbInfoData := edbInfoDataList[0]
+	endEdbInfoData := edbInfoDataList[len(edbInfoDataList)-1]
+
+	// 计算起始和结束日期间实际的天数
+	startDate, _ := time.ParseInLocation(utils.FormatDate, startEdbInfoData.DataTime, time.Local)
+	endDate, _ := time.ParseInLocation(utils.FormatDate, endEdbInfoData.DataTime, time.Local)
+	actualDays := endDate.Sub(startDate).Hours() / 24
+
+	// 生成365个数据点,首先处理已有数据
+	for _, v := range edbInfoDataList {
+		handleDataMap[v.DataTime] = v.Value
+		dataTimeList = append(dataTimeList, v.DataTime)
+		valueList = append(valueList, v.Value)
+	}
+
+	// 如果已有数据跨越天数不足365天,则对缺失的日期进行线性插值
+	if actualDays < 365 {
+		// 使用已有数据点生成线性方程(这里简化处理,实际可能需更细致处理边界情况)
+		var a, b float64
+		coordinateData := []utils.Coordinate{
+			{X: 1, Y: startEdbInfoData.Value},
+			{X: float64(len(edbInfoDataList)), Y: endEdbInfoData.Value},
+		}
+		a, b = utils.GetLinearResult(coordinateData)
+		if math.IsNaN(a) || math.IsNaN(b) {
+			err = errors.New("线性方程公式生成失败")
+			return
+		}
+
+		// 对剩余日期进行插值
+		for i := 1; i < 365; i++ {
+			day := startDate.AddDate(0, 0, i)
+			if _, exists := handleDataMap[day.Format(utils.FormatDate)]; !exists {
+				aDecimal := decimal.NewFromFloat(a)
+				xDecimal := decimal.NewFromInt(int64(i) + 1)
+				bDecimal := decimal.NewFromFloat(b)
+
+				val, _ := aDecimal.Mul(xDecimal).Add(bDecimal).Round(4).Float64()
+				handleDataMap[day.Format(utils.FormatDate)] = val
+				dataTimeList = append(dataTimeList, day.Format(utils.FormatDate))
+				valueList = append(valueList, val)
+			}
+		}
+	}
+
+	return
+}