package residual_analysis_service import ( "encoding/json" "eta/eta_api/models/data_manage" "eta/eta_api/models/residual_analysis_model" "eta/eta_api/models/system" "eta/eta_api/utils" "fmt" "math" "strconv" "time" ) func ResidualAnalysisPreview(req residual_analysis_model.ResidualAnalysisReq) (residual_analysis_model.ResidualAnalysisResp, error) { mappingList, err := data_manage.GetChartEdbMappingListByEdbInfoIdList([]int{req.EdbInfoIdA, req.EdbInfoIdB}) if err != nil { return residual_analysis_model.ResidualAnalysisResp{}, fmt.Errorf("获取图表,指标信息失败,Err:%s", err.Error()) } var edbInfoMappingA, edbInfoMappingB *data_manage.ChartEdbInfoMapping for _, v := range mappingList { if v.EdbInfoId == req.EdbInfoIdA { edbInfoMappingA = v } if v.EdbInfoId == req.EdbInfoIdB { edbInfoMappingB = v } } if edbInfoMappingA == nil { return residual_analysis_model.ResidualAnalysisResp{}, fmt.Errorf("指标A不存在") } if edbInfoMappingB == nil { return residual_analysis_model.ResidualAnalysisResp{}, fmt.Errorf("指标B不存在") } // 时间处理 var startDate, endDate string switch req.DateType { case 0: startDate = req.StartDate endDate = req.EndDate case 1: startDate = req.StartDate endDate = "" default: startDate = utils.GetPreYearTime(req.DateType) endDate = "" } resp := residual_analysis_model.ResidualAnalysisResp{} // 原始图表信息 originalEdbList := make([]residual_analysis_model.ResidualAnalysisChartEdbInfoMapping, 0) originalEdbList, err = fillOriginalChart(req, mappingList, startDate, endDate, edbInfoMappingA, edbInfoMappingB, originalEdbList) if err != nil { return residual_analysis_model.ResidualAnalysisResp{}, err } originalChartInfo := createChartInfoResp(req, startDate, endDate, edbInfoMappingA.EdbName+"与"+edbInfoMappingB.EdbName) resp.OriginalChartData = residual_analysis_model.ChartResp{ ChartInfo: originalChartInfo, EdbInfoList: originalEdbList, } // 如果只需要第一张图表的数据 直接返回,避免继续处理 if req.QueryType == 1 { return resp, nil } dataAList, ok := edbInfoMappingA.DataList.([]*data_manage.EdbDataList) if !ok { return residual_analysis_model.ResidualAnalysisResp{}, fmt.Errorf("数据类型转换失败") } indexADataMap := map[string]*data_manage.EdbDataList{} for _, indexData := range dataAList { indexADataMap[indexData.DataTime] = indexData } // 映射图表信息 mappingEdbList, a, b, r, err := fillMappingChartInfo(req, edbInfoMappingA, edbInfoMappingB, originalEdbList, indexADataMap) if err != nil { return residual_analysis_model.ResidualAnalysisResp{}, err } mappingChartInfo := createChartInfoResp(req, startDate, endDate, edbInfoMappingA.EdbName+"与"+edbInfoMappingB.EdbName+"映射"+edbInfoMappingA.EdbName) resp.MappingChartData = residual_analysis_model.ChartResp{ ChartInfo: mappingChartInfo, EdbInfoList: mappingEdbList, } // 残差图表信息 residualEdbList, R2, err := fillResidualChartInfo(edbInfoMappingA, edbInfoMappingB, mappingEdbList) if err != nil { return residual_analysis_model.ResidualAnalysisResp{}, err } residualChartInfo := createChartInfoResp(req, startDate, endDate, edbInfoMappingA.EdbName+"与"+edbInfoMappingA.EdbName+"映射残差/"+edbInfoMappingB.EdbName) resp.ResidualChartData = residual_analysis_model.ChartResp{ ChartInfo: residualChartInfo, EdbInfoList: residualEdbList, } if req.ResidualType == 2 { resp.A = a resp.B = b resp.R = r resp.R2 = R2 } return resp, nil } func createChartInfoResp(req residual_analysis_model.ResidualAnalysisReq, startDate, endDate, chartName string) residual_analysis_model.ResidualAnalysisChartInfo { return residual_analysis_model.ResidualAnalysisChartInfo{ Calendar: `公历`, Source: utils.CHART_SOURCE_DEFAULT, DateType: req.DateType, StartDate: startDate, EndDate: endDate, ChartType: utils.CHART_TYPE_CURVE, ChartName: chartName, } } func fillResidualChartInfo(edbInfoMappingA *data_manage.ChartEdbInfoMapping, edbInfoMappingB *data_manage.ChartEdbInfoMapping, mappingEdbList []residual_analysis_model.ResidualAnalysisChartEdbInfoMapping) ([]residual_analysis_model.ResidualAnalysisChartEdbInfoMapping, float64, error) { // 计算公式 映射残差 = 因变量指标 - 映射指标 var edbInfoA, edbInfoB residual_analysis_model.ResidualAnalysisChartEdbInfoMapping if mappingEdbList[0].EdbInfoId == edbInfoMappingA.EdbInfoId { edbInfoA = mappingEdbList[0] edbInfoB = mappingEdbList[1] } else { edbInfoA = mappingEdbList[1] edbInfoB = mappingEdbList[0] } dataAList, ok := edbInfoA.DataList.([]*data_manage.EdbDataList) if !ok { return nil, 0, fmt.Errorf("数据类型转换失败") } edbData := dataAList dataBList, ok := edbInfoB.DataList.([]*data_manage.EdbDataList) if !ok { return nil, 0, fmt.Errorf("数据类型转换失败") } var indexDataBMap = make(map[string]*data_manage.EdbDataList) for _, data := range dataBList { indexDataBMap[data.DataTime] = data } // 求R2 var valueB, sumValueA, averageValueA, residualQuadraticSum, totalQuadraticSum, R2 float64 for _, indexData := range edbData { // 因变量的值总和 sumValueA += indexData.Value } // 因变量平均值 averageValueA = sumValueA / float64(len(edbData)) for _, indexData := range edbData { if dataB, ok := indexDataBMap[indexData.DataTime]; ok { valueB = dataB.Value } else { valueB = 0 } // 总因变量平方和 totalQuadraticSum += math.Pow(indexData.Value-averageValueA, 2) // 补全残差值 indexData.Value = indexData.Value - valueB // 残差平方和 residualQuadraticSum += math.Pow(indexData.Value, 2) } // 计算R2 公式:R2=1-SSE/SST R2越大,越符合线性 R2 = 1 - 残差平方和/总平方和 R2 = 1 - residualQuadraticSum/totalQuadraticSum mappingEdb := make([]residual_analysis_model.ResidualAnalysisChartEdbInfoMapping, len(mappingEdbList)) copy(mappingEdb, mappingEdbList) for i, mapping := range mappingEdb { if mapping.EdbInfoId != edbInfoMappingA.EdbInfoId { mappingEdb[i].DataList = edbData mappingEdb[i].EdbName = edbInfoMappingA.EdbName + "映射残差/" + edbInfoMappingB.EdbName mappingEdb[i].IsAxis = 1 mappingEdb[i].ChartColor = `#00F` } else { mappingEdb[i].IsAxis = 0 mappingEdb[i].ChartColor = `#F00` } } return mappingEdb, R2, nil } func fillMappingChartInfo(req residual_analysis_model.ResidualAnalysisReq, edbInfoMappingA *data_manage.ChartEdbInfoMapping, edbInfoMappingB *data_manage.ChartEdbInfoMapping, originalEdbList []residual_analysis_model.ResidualAnalysisChartEdbInfoMapping, indexADataMap map[string]*data_manage.EdbDataList) ([]residual_analysis_model.ResidualAnalysisChartEdbInfoMapping, float64, float64, float64, error) { // 计算公式:Y=aX+b,Y为映射后的指标,X为自变量指标 // 正序:a=(L2-L1)/(R2-R1) b=L2-R2*a // 逆序:a=(L2-L1)/(R1-R2) b=L2-R1*a // L2:左轴下限 R2:右轴上限 L1:左轴上限 R1:右轴下限 var a, b, r float64 // 映射残差 计算a,b if req.ResidualType == 1 { if req.IsOrder { a = (req.LeftIndexMax - req.LeftIndexMin) / (req.RightIndexMin - req.RightIndexMax) b = req.LeftIndexMax - req.RightIndexMin*a } else { a = (req.LeftIndexMax - req.LeftIndexMin) / (req.RightIndexMax - req.RightIndexMin) b = req.LeftIndexMax - req.RightIndexMax*a } } dataList, ok := edbInfoMappingB.DataList.([]*data_manage.EdbDataList) if !ok { return nil, a, b, r, fmt.Errorf("数据类型转换失败") } // 领先指标 dataList进行数据处理 if req.IndexType == 2 { if req.LeadValue < 0 { return nil, a, b, r, fmt.Errorf("领先值不能小于0") } else if req.LeadValue > 0 { for _, indexData := range dataList { switch req.LeadFrequency { case "天": indexData.DataTime = utils.GetNextDayN(indexData.DataTime, req.LeadValue) case "周": indexData.DataTime = utils.GetNextDayN(indexData.DataTime, req.LeadValue*7) case "月": indexData.DataTime = utils.TimeToString(utils.AddDate(utils.StringToTime(indexData.DataTime), 0, req.LeadValue), utils.YearMonthDay) case "季": indexData.DataTime = utils.TimeToString(utils.AddDate(utils.StringToTime(indexData.DataTime), 0, req.LeadValue*3), utils.YearMonthDay) case "年": indexData.DataTime = utils.TimeToString(utils.AddDate(utils.StringToTime(indexData.DataTime), req.LeadValue, 0), utils.YearMonthDay) } } } } // 指标B数据补充 for index := 0; index < len(dataList)-1; index++ { // 获取当前数据和下一个数据 beforeIndexData := dataList[index] afterIndexData := dataList[index+1] // 从最早时间开始,补充时间为自然日 if utils.IsMoreThanOneDay(beforeIndexData.DataTime, afterIndexData.DataTime) { // 创建补充数据 replenishIndexData := data_manage.EdbDataList{ DataTime: utils.GetNextDay(beforeIndexData.DataTime), DataTimestamp: time.Now().UnixMilli(), Value: beforeIndexData.Value, } // 将补充数据插入到数据列表 dataList = append(dataList, &replenishIndexData) } } // 拟合残差 计算a,b var coordinateList []utils.Coordinate if req.ResidualType == 2 { for _, indexData := range dataList { if _, ok := indexADataMap[indexData.DataTime]; ok { coordinate := utils.Coordinate{ X: indexData.Value, Y: indexADataMap[indexData.DataTime].Value, } coordinateList = append(coordinateList, coordinate) } } a, b = utils.GetLinearResult(coordinateList) r = utils.CalculationDecisive(coordinateList) } // 根据指标A的时间key,在B的映射指标中筛选出对应的值 var dataBList []*data_manage.EdbDataList for _, indexData := range dataList { if _, ok := indexADataMap[indexData.DataTime]; ok { indexDataCopy := *indexData // 计算指标B映射值 indexDataCopy.Value = math.Round((a*indexData.Value+b)*10000) / 10000 // 将副本添加到 dataBList dataBList = append(dataBList, &indexDataCopy) } } mappingEdbList := make([]residual_analysis_model.ResidualAnalysisChartEdbInfoMapping, len(originalEdbList)) copy(mappingEdbList, originalEdbList) for i, mapping := range mappingEdbList { if mapping.EdbInfoId != req.EdbInfoIdA { mappingEdbList[i].EdbInfoId = 0 mappingEdbList[i].EdbCode = "" mappingEdbList[i].IsAxis = 1 mappingEdbList[i].EdbName = edbInfoMappingB.EdbName + "映射" + edbInfoMappingA.EdbName mappingEdbList[i].DataList = dataBList } } return mappingEdbList, a, b, r, nil } func fillOriginalChart(req residual_analysis_model.ResidualAnalysisReq, mappingList []*data_manage.ChartEdbInfoMapping, startDate string, endDate string, edbInfoMappingA *data_manage.ChartEdbInfoMapping, edbInfoMappingB *data_manage.ChartEdbInfoMapping, originalEdbList []residual_analysis_model.ResidualAnalysisChartEdbInfoMapping) ([]residual_analysis_model.ResidualAnalysisChartEdbInfoMapping, error) { for _, v := range mappingList { var edbInfoMapping residual_analysis_model.ResidualAnalysisChartEdbInfoMapping edbInfoMapping.EdbInfoType = 1 edbInfoMapping.IsOrder = false edbInfoMapping.IsAxis = 1 edbInfoMapping.ChartColor = `#00F` edbInfoMapping.ChartWidth = 3 // 获取图表中的指标数据 dataList, err := data_manage.GetEdbDataList(v.Source, v.SubSource, v.EdbInfoId, startDate, endDate) if err != nil { return nil, fmt.Errorf("获取指标数据失败,Err:%s", err.Error()) } if v.EdbInfoId == req.EdbInfoIdB { edbInfoMapping.LeadValue = req.LeadValue edbInfoMapping.LeadUnit = req.LeadFrequency edbInfoMapping.EdbInfoType = req.IndexType edbInfoMapping.IsOrder = req.IsOrder edbInfoMapping.IsAxis = 0 edbInfoMapping.ChartColor = `#F00` edbInfoMapping.ChartWidth = 1 edbInfoMappingB.DataList = dataList } else { edbInfoMappingA.DataList = dataList } edbInfoMapping.EdbInfoId = v.EdbInfoId edbInfoMapping.EdbName = v.EdbName edbInfoMapping.EdbCode = v.EdbCode edbInfoMapping.Unit = v.Unit edbInfoMapping.Frequency = v.Frequency edbInfoMapping.Source = v.Source edbInfoMapping.SourceName = v.SourceName edbInfoMapping.MinValue = v.MinValue edbInfoMapping.MaxValue = v.MaxValue edbInfoMapping.LatestDate = v.LatestDate edbInfoMapping.LatestValue = v.LatestValue edbInfoMapping.DataList = dataList originalEdbList = append(originalEdbList, edbInfoMapping) } return originalEdbList, nil } func ContrastPreview(indexCode string) (residual_analysis_model.ResidualAnalysisChartEdbInfoMapping, error) { var condition string var pars []interface{} if indexCode != "" { condition += " and edb_code=?" pars = append(pars, indexCode) } edbInfo, err := data_manage.GetEdbInfoByCondition(condition, pars) if err != nil { return residual_analysis_model.ResidualAnalysisChartEdbInfoMapping{}, err } if edbInfo == nil { return residual_analysis_model.ResidualAnalysisChartEdbInfoMapping{}, fmt.Errorf("指标不存在") } dataList, err := data_manage.GetEdbDataList(edbInfo.Source, edbInfo.SubSource, edbInfo.EdbInfoId, "", "") var resp residual_analysis_model.ResidualAnalysisChartEdbInfoMapping resp.EdbInfoId = edbInfo.EdbInfoId resp.EdbCode = edbInfo.EdbCode resp.ChartColor = "#F00" resp.SourceName = edbInfo.SourceName resp.EdbName = edbInfo.EdbName resp.Unit = edbInfo.Unit resp.Frequency = edbInfo.Frequency resp.MinValue = edbInfo.MinValue resp.MaxValue = edbInfo.MaxValue resp.DataList = dataList return resp, nil } func SaveResidualAnalysis(req residual_analysis_model.ResidualAnalysisIndexSaveReq, sysUser *system.Admin) error { // 验证分类是否存在 classifyCount, err := data_manage.GetEdbClassifyCountById(req.ClassifyId) if err != nil { return err } if classifyCount <= 0 { return fmt.Errorf("分类不存在") } // 校验名称是否重复 var condition string var pars []interface{} condition += " and source = ? AND edb_name=?" pars = append(pars, req.Source, req.EdbName) edbInfoByCondition, err := data_manage.GetEdbInfoByCondition(condition, pars) if err != nil && err.Error() != utils.ErrNoRow() { return err } // 获取指标数据最大值 最小值 最后更新时间 最后更新时间对应的值 var indexMax, indexMin, indexLatestValue float64 var indexLatestDate string if len(req.DataList) > 0 { latestTime, _ := time.Parse(utils.YearMonthDay, req.DataList[0].DataTime) for _, data := range req.DataList { // 比较最大值 if data.Value > indexMax { indexMax = data.Value } // 比较最小值 if data.Value < indexMin { indexMin = data.Value } // 比较最新时间和对应值 currentTime, err := time.Parse(utils.YearMonthDay, data.DataTime) if err != nil { // 时间解析失败,跳过此项 continue } // 如果当前时间更晚 if currentTime.After(latestTime) { latestTime = currentTime indexLatestDate = data.DataTime indexLatestValue = data.Value } } } // 更新保存指标和配置的映射关系 mappingList, err := residual_analysis_model.GetConfigMappingListByConfigId(req.ConfigId) if err != nil { return err } // 判断是更新还是修改 看指标配置映射中,是否存在对应指标 存在 则更新 不存在 则新增 var edbInfoMapping residual_analysis_model.CalculateResidualAnalysisConfigMapping for _, mapping := range mappingList { if req.IndexType == mapping.IndexType && req.IndexType != 0 { edbInfoMapping = mapping } } var edbInfoId int64 var edbCode string // 更新or新增 if edbInfoMapping.EdbInfoId > 0 { // 查询指标库指标 edbInfo, err := data_manage.GetEdbInfoById(int(edbInfoMapping.EdbInfoId)) if err != nil { return err } if edbInfo == nil { return fmt.Errorf("指标不存在") } edbInfoId = int64(edbInfo.EdbInfoId) edbCode = edbInfo.EdbCode if edbInfoByCondition.EdbInfoId != edbInfo.EdbInfoId { return fmt.Errorf("指标名称重复") } // 须补充更新指标最大值,最小值,数据最新时间,数据最新值 edbInfo.MaxValue = indexMax edbInfo.MinValue = indexMin edbInfo.LatestDate = indexLatestDate edbInfo.LatestValue = indexLatestValue err = edbInfo.Update([]string{"min_value", "max_value", "latest_date", "latest_value"}) if err != nil { return err } // 删除对应得指标数据 err = residual_analysis_model.DeleteResidualAnalysisDataByEdbCode(req.EdbCode) if err != nil { return fmt.Errorf("删除指标数据失败") } } else { if edbInfoByCondition != nil { return fmt.Errorf("指标名称重复") } // 新增指标 edbCode, err = utils.GenerateEdbCode(1, "") if err != nil { return err } timestamp := strconv.FormatInt(time.Now().UnixNano(), 10) edbInfoId, err = data_manage.AddEdbInfo(&data_manage.EdbInfo{ EdbCode: edbCode, UniqueCode: utils.MD5(utils.CHART_PREFIX + "_" + timestamp), EdbName: req.EdbName, EdbNameEn: req.EdbNameEn, ClassifyId: req.ClassifyId, EdbType: req.EdbType, Unit: req.Unit, UnitEn: req.UnitEn, Frequency: req.Frequency, Source: req.Source, SourceName: "残差分析", Calendar: req.Calendar, SysUserRealName: sysUser.RealName, SysUserId: sysUser.AdminId, LatestDate: indexLatestDate, LatestValue: indexLatestValue, CreateTime: time.Now(), ModifyTime: time.Now(), }) if err != nil { return err } } // 新增数据 for i := range req.DataList { req.DataList[i].EdbDataId = 0 req.DataList[i].EdbInfoId = int(edbInfoId) req.DataList[i].EdbCode = edbCode } _, err = residual_analysis_model.AddResidualAnalysisData(req.DataList) if err != nil { return err } var indexMap = make(map[int64]residual_analysis_model.CalculateResidualAnalysisConfigMapping) for _, mapping := range mappingList { indexMap[mapping.EdbInfoId] = mapping } if _, ok := indexMap[edbInfoId]; !ok { _, err = residual_analysis_model.SaveConfigMapping(residual_analysis_model.CalculateResidualAnalysisConfigMapping{ CalculateResidualAnalysisConfigId: req.ConfigId, EdbInfoId: edbInfoId, ResidualType: req.ResidualType, IndexType: req.IndexType, CreateTime: time.Now(), ModifyTime: time.Now(), }) if err != nil { return err } } if _, ok := indexMap[int64(req.EdbInfoIdA)]; !ok { _, err = residual_analysis_model.SaveConfigMapping(residual_analysis_model.CalculateResidualAnalysisConfigMapping{ CalculateResidualAnalysisConfigId: req.ConfigId, EdbInfoId: int64(req.EdbInfoIdA), ResidualType: req.ResidualType, IndexType: 3, CreateTime: time.Now(), ModifyTime: time.Now(), }) if err != nil { return err } } if _, ok := indexMap[int64(req.EdbInfoIdB)]; !ok { _, err = residual_analysis_model.SaveConfigMapping(residual_analysis_model.CalculateResidualAnalysisConfigMapping{ CalculateResidualAnalysisConfigId: req.ConfigId, EdbInfoId: int64(req.EdbInfoIdB), ResidualType: req.ResidualType, IndexType: 4, CreateTime: time.Now(), ModifyTime: time.Now(), }) if err != nil { return err } } return nil } func ResidualAnalysisDetail(edbInfoId int) (residual_analysis_model.ResidualAnalysisDetailResp, error) { // 通过指标配置映射表 拿到配置id,再获取关联的所有指标信息 var condition string var pars []interface{} condition += " and edb_info_id=?" pars = append(pars, edbInfoId) mappingList, err := residual_analysis_model.GetConfigMappingListByCondition(condition, pars) if err != nil { return residual_analysis_model.ResidualAnalysisDetailResp{}, err } if len(mappingList) <= 0 { return residual_analysis_model.ResidualAnalysisDetailResp{}, fmt.Errorf("指标不存在") } mapping := mappingList[0] configMappingList, err := residual_analysis_model.GetConfigMappingListByConfigId(mapping.CalculateResidualAnalysisConfigId) if err != nil { return residual_analysis_model.ResidualAnalysisDetailResp{}, err } var edbInfoIdList []int64 var edbInfoMap = make(map[int64]residual_analysis_model.CalculateResidualAnalysisConfigMapping) var mappgingFlag = false var residualFlag = false for _, v := range configMappingList { edbInfoIdList = append(edbInfoIdList, v.EdbInfoId) edbInfoMap[v.EdbInfoId] = v if v.IndexType == 1 { mappgingFlag = true } else if v.IndexType == 2 { residualFlag = true } } condition = "" pars = []interface{}{} condition += ` and edb_info_id in(` + utils.GetOrmInReplace(len(edbInfoIdList)) + `)` for _, id := range edbInfoIdList { pars = append(pars, id) } edbInfoList, err := data_manage.GetEdbInfoListByCond(condition, pars) if err != nil { return residual_analysis_model.ResidualAnalysisDetailResp{}, err } // 获取配置 configInfo, err := residual_analysis_model.GetResidualAnalysisConfigById(mapping.CalculateResidualAnalysisConfigId) if err != nil { return residual_analysis_model.ResidualAnalysisDetailResp{}, err } var edbInfoListResp []*residual_analysis_model.DetailEdbInfoList var dependentEdbInfo residual_analysis_model.DetailEdbInfoList var independentEdbInfo residual_analysis_model.DetailEdbInfoList for _, edbInfo := range edbInfoList { var indexType int if _, ok := edbInfoMap[int64(edbInfo.EdbInfoId)]; ok { indexType = edbInfoMap[int64(edbInfo.EdbInfoId)].IndexType } info := residual_analysis_model.DetailEdbInfoList{ EdbInfoId: edbInfo.EdbInfoId, EdbInfoType: edbInfo.EdbInfoType, IndexType: indexType, SourceName: edbInfo.SourceName, Source: edbInfo.Source, EdbCode: edbInfo.EdbCode, EdbName: edbInfo.EdbName, EdbNameEn: edbInfo.EdbNameEn, Unit: edbInfo.Unit, UnitEn: edbInfo.UnitEn, Frequency: edbInfo.Frequency, FrequencyEn: edbInfo.FrequencyEn, ClassifyId: edbInfo.ClassifyId, } edbInfoListResp = append(edbInfoListResp, &info) if indexType == 3 { dependentEdbInfo = info } else if indexType == 4 { independentEdbInfo = info } } // 补充表格中 映射指标或者残差指标 if mappgingFlag && !residualFlag { info := residual_analysis_model.DetailEdbInfoList{ IndexType: 2, EdbName: independentEdbInfo.EdbName + "映射残差/" + dependentEdbInfo.EdbName, EdbNameEn: dependentEdbInfo.EdbNameEn, Unit: dependentEdbInfo.Unit, UnitEn: dependentEdbInfo.UnitEn, Frequency: dependentEdbInfo.Frequency, FrequencyEn: dependentEdbInfo.FrequencyEn, ClassifyId: dependentEdbInfo.ClassifyId, } edbInfoListResp = append(edbInfoListResp, &info) } else if !mappgingFlag && residualFlag { info := residual_analysis_model.DetailEdbInfoList{ IndexType: 1, EdbName: dependentEdbInfo.EdbName + "映射" + independentEdbInfo.EdbName, EdbNameEn: dependentEdbInfo.EdbNameEn, Unit: dependentEdbInfo.Unit, UnitEn: dependentEdbInfo.UnitEn, Frequency: dependentEdbInfo.Frequency, FrequencyEn: dependentEdbInfo.FrequencyEn, ClassifyId: dependentEdbInfo.ClassifyId, } edbInfoListResp = append(edbInfoListResp, &info) } resp := residual_analysis_model.ResidualAnalysisDetailResp{ ConfigInfo: &configInfo, EdbInfoList: edbInfoListResp, } return resp, nil } func SaveResidualAnalysisConfig(req residual_analysis_model.ResidualAnalysisReq, sysUser *system.Admin) (int64, error) { config := residual_analysis_model.ResidualAnalysisConfigVo{ DateType: req.DateType, StartDate: req.StartDate, EndDate: req.EndDate, IsOrder: req.IsOrder, IndexType: req.IndexType, LeadValue: req.LeadValue, LeadFrequency: req.LeadFrequency, LeftIndexMin: req.LeftIndexMin, LeftIndexMax: req.LeftIndexMax, RightIndexMin: req.RightIndexMin, RightIndexMax: req.RightIndexMax, ResidualIndexMin: req.ResidualIndexMin, ResidualIndexMax: req.ResidualIndexMax, ContrastIndexMin: req.ContrastIndexMin, ContrastIndexMax: req.ContrastIndexMax, } // 转换为json格式 configJson, err := json.Marshal(config) if err != nil { return 0, err } var condition string var pars []interface{} // 新增or更新 if req.EdbInfoId > 0 { condition += " and edb_info_id=?" pars = append(pars, req.EdbInfoId) configMappings, err := residual_analysis_model.GetConfigMappingListByCondition(condition, pars) if err != nil { return 0, err } if len(configMappings) > 0 { mapping := configMappings[0] configInfo, err := residual_analysis_model.GetResidualAnalysisConfigById(mapping.CalculateResidualAnalysisConfigId) if err != nil { return 0, err } configInfo.Config = string(configJson) err = residual_analysis_model.UpdateResidualAnalysisConfig(configInfo) if err != nil { return 0, err } } } analysisConfig := residual_analysis_model.CalculateResidualAnalysisConfig{ Config: string(configJson), SysUserId: sysUser.AdminId, CreateTime: time.Now(), ModifyTime: time.Now(), } configId, err := residual_analysis_model.SaveResidualAnalysisConfig(analysisConfig) if err != nil { return 0, err } return configId, nil } func CheckResidualAnalysisExist(configId int) (int64, error) { configMappingList, err := residual_analysis_model.GetConfigMappingListByConfigId(configId) if err != nil { return 0, err } var configMapping residual_analysis_model.CalculateResidualAnalysisConfigMapping for _, mapping := range configMappingList { if mapping.IndexType == 2 { configMapping = mapping } } return configMapping.EdbInfoId, nil }