package chart import ( "context" "encoding/json" "fmt" "github.com/gin-gonic/gin" "hongze/hongze_yb/controller/response" "hongze/hongze_yb/global" "hongze/hongze_yb/models/request" responseModel "hongze/hongze_yb/models/response" "hongze/hongze_yb/models/response/chart_info" chartEdbMappingModel "hongze/hongze_yb/models/tables/chart_edb_mapping" chartInfoModel "hongze/hongze_yb/models/tables/chart_info" "hongze/hongze_yb/models/tables/chart_info_correlation" "hongze/hongze_yb/models/tables/chart_info_log" "hongze/hongze_yb/models/tables/multiple_graph_config_chart_mapping" "hongze/hongze_yb/models/tables/yb_my_chart" "hongze/hongze_yb/services/alarm_msg" "hongze/hongze_yb/services/chart" "hongze/hongze_yb/services/chart/correlation" future_goodServ "hongze/hongze_yb/services/chart/future_good" "hongze/hongze_yb/services/user" "hongze/hongze_yb/utils" "io/ioutil" "strconv" "strings" "time" ) // CommonChartInfoDetailFromUniqueCode 获取图表详情(通用) // @Tags 图库模块 // @Summary 获取图表详情 // @Description 获取图表详情 // @Security ApiKeyAuth // @Param Authorization header string true "Bearer 31a165baebe6dec616b1f8f3207b4273" // @Accept json // @Product json // @Param DateType query string false "时间段:1-00年至今; 2-10年至今; 3-15年至今; 4-21年至今; 5-指定区间; 6-指定年月至今; 7-18年至今; 8-19年至今; 9-20年至今" // @Param ClassifyId query string false "图表分类ID" // @Success 200 {object} chart_info.ChartInfoDetailResp // @failure 400 {string} string "图表详情获取失败" // @Router /my_chart/common/detail [get] func CommonChartInfoDetailFromUniqueCode(c *gin.Context) { // 图表ID reqChartInfoId := c.DefaultQuery("ChartInfoId", "") if reqChartInfoId == "" { response.Fail("参数有误:图表ID", c) return } chartInfoId, _ := strconv.Atoi(reqChartInfoId) reqMyChartClassifyId := c.DefaultQuery("MyChartClassifyId", "") myChartClassifyId, _ := strconv.Atoi(reqMyChartClassifyId) chartInfo := new(chartInfoModel.ChartInfoView) chartInfo, err := chartInfoModel.GetChartInfoViewById(chartInfoId) if err != nil { if err == utils.ErrNoRow { response.FailMsg("图表不存在,请刷新页面", "图表不存在,请刷新页面", c) return } response.FailMsg(`获取失败`, "获取图表信息失败, Err:"+err.Error(), c) return } switch chartInfo.Source { case utils.CHART_SOURCE_DEFAULT: resp, isOk, msg, errMsg := getChartInfoDetail(chartInfo, myChartClassifyId, user.GetInfoByClaims(c)) if !isOk { response.FailMsg(msg, errMsg, c) return } response.OkData("获取成功", resp, c) return case utils.CHART_SOURCE_FUTURE_GOOD: resp, isOk, msg, errMsg := getFutureGoodChartInfoDetail(chartInfo, myChartClassifyId, user.GetInfoByClaims(c)) if !isOk { response.FailMsg(msg, errMsg, c) return } response.OkData("获取成功", resp, c) return case utils.CHART_SOURCE_CORRELATION, utils.CHART_SOURCE_ROLLING_CORRELATION: resp, isOk, msg, errMsg := getCorrelationChartInfoDetail(chartInfo, myChartClassifyId, user.GetInfoByClaims(c)) if !isOk { response.FailMsg(msg, errMsg, c) return } response.OkData("获取成功", resp, c) return default: msg := "错误的图表" errMsg := "错误的图表" response.FailMsg(msg, errMsg, c) return } } // getFutureGoodChartInfoDetail 获取商品价格曲线图表详情 func getFutureGoodChartInfoDetail(chartInfo *chartInfoModel.ChartInfoView, myChartClassifyId int, userInfo user.UserInfo) (resp *chart_info.ChartInfoDetailResp, isOk bool, msg, errMsg string) { resp = new(chart_info.ChartInfoDetailResp) // 获取图表信息 var err error chartInfoId := chartInfo.ChartInfoId startDate := chartInfo.StartDate endDate := chartInfo.EndDate // 兼容日期错误 { if strings.Count(startDate, "-") == 1 { startDate = startDate + "-01" } if strings.Count(endDate, "-") == 1 { endDate = endDate + "-01" } } edbInfoMapping, err := chartEdbMappingModel.GetEtaEdbChartEdbMapping(chartInfoId) if err != nil { msg = "获取失败" errMsg = "获取图表,现货指标信息失败,Err:" + err.Error() return } futureGoodEdbInfoMapping, err := chartEdbMappingModel.GetFutureGoodEdbChartEdbMapping(chartInfoId) if err != nil { msg = "获取失败" errMsg = "获取图表的期货商品指标信息失败,Err:" + err.Error() return } // 商品价格曲线图的一些配置 var barConfig request.BarChartInfoReq barChartInfoDateList := make([]request.BarChartInfoDateReq, 0) barChartInfoSort := request.BarChartInfoSortReq{} if chartInfo.BarConfig == `` { msg = "商品价格曲线图未配置" errMsg = "商品价格曲线图未配置" return } err = json.Unmarshal([]byte(chartInfo.BarConfig), &barConfig) if err != nil { msg = "商品价格曲线图配置异常" errMsg = "商品价格曲线图配置异常" return } barChartInfoDateList = barConfig.DateList barChartInfoSort = barConfig.Sort // 获取图表中的指标数据 barConfigEdbInfoIdList, edbList, xEdbIdValue, xDataList, yDataList, sourceArr, err := future_goodServ.GetChartEdbData(chartInfoId, startDate, endDate, edbInfoMapping, futureGoodEdbInfoMapping, barChartInfoDateList, barChartInfoSort) if err != nil { msg = "获取失败" errMsg = "获取图表,指标信息失败,Err:" + err.Error() return } if len(edbList) <= 0 { msg = "商品价格曲线图表指标异常" errMsg = "商品价格曲线图表异常" return } sourceArr = append(sourceArr, "弘则研究") chartInfo.ChartSource = strings.Join(sourceArr, ",") for _, v := range edbList { // 指标别名 if barConfigEdbInfoIdList != nil && len(barConfigEdbInfoIdList) > 0 { for _, reqEdb := range barConfigEdbInfoIdList { if v.EdbInfoId == reqEdb.EdbInfoId { v.EdbAliasName = reqEdb.Name v.EdbAliasNameEn = reqEdb.NameEn } } } } baseEdbInfo := edbList[0] //现货指标 chartInfo.UnitEn = baseEdbInfo.UnitEn // 访问记录-仅普通用户记录 ok, _, _ := user.GetAdminByUserInfo(userInfo) if !ok { go chart.SaveChartVisitLog(userInfo, chartInfo, myChartClassifyId) } // 用户是否有收藏该图表 { ob := new(yb_my_chart.YbMyChart) cond := `user_id = ? AND chart_info_id = ?` pars := make([]interface{}, 0) pars = append(pars, userInfo.UserID, chartInfo.ChartInfoId) exists, e := ob.FetchByCondition(cond, pars) if e != nil && e != utils.ErrNoRow { msg = `操作失败` errMsg = "获取用户图表失败, Err: " + e.Error() return } myChartInfo := new(responseModel.MyChartItem) if exists != nil && exists.MyChartID > 0 { myChartInfo.MyChartID = exists.MyChartID myChartInfo.MyChartClassifyID = exists.MyChartClassifyID myChartInfo.ChartInfoID = exists.ChartInfoID myChartInfo.ChartName = exists.ChartName myChartInfo.UniqueCode = exists.UniqueCode myChartInfo.ChartImage = exists.ChartImage myChartInfo.UserID = exists.UserID myChartInfo.ReportID = exists.ReportID myChartInfo.ReportChapterID = exists.ReportChapterID myChartInfo.CreateTime = utils.TimeTransferString(utils.FormatDateTime, exists.CreateTime) } resp.MyChartInfo = myChartInfo } resp.ChartInfo = chartInfo resp.EdbInfoList = edbList resp.XEdbIdValue = xEdbIdValue resp.XDataList = xDataList resp.YDataList = yDataList isOk = true return } // RefreshFutureGoodChartInfo 刷新商品价格曲线图表信息 // @Tags 图库模块 // @Summary 刷新图表信息 // @Description 刷新图表信息 // @Security ApiKeyAuth // @Param Authorization header string true "Bearer 31a165baebe6dec616b1f8f3207b4273" // @Accept json // @Product json // @Param data body chartInfoModel.SaveChartInfoReq true "请求参数" // @Success 200 {string} string "操作成功" // @failure 400 {string} string "操作失败" // @Router /my_chart/future_good/refreshChartInfo [post] func RefreshFutureGoodChartInfo(c *gin.Context) { // 参数校验 var req chartInfoModel.RefreshChartInfoReq if c.ShouldBind(&req) != nil { response.Fail("参数异常", c) return } chartInfoId := req.ChartInfoId if chartInfoId == 0 { response.Fail("参数有误", c) return } //userInfo := user.GetInfoByClaims(c) //ok, _, err := user.GetAdminByUserInfo(userInfo) //if err != nil { // response.FailMsg("刷新失败", "RefreshChartInfo-获取系统用户信息失败"+err.Error(), c) // return //} //if !ok { // // 普通用户刷新频率限制-每个用户/图/天/2次 // cacheKey := utils.HZ_CHART_LIB_DETAIL + "YB_REFRESH_LIMIT_" + strconv.Itoa(chartInfoId) + "_" + strconv.Itoa(int(userInfo.UserID)) // fmt.Println("refreshCacheKey:", cacheKey) // countUserRefresh, _ := global.Redis.Get(context.TODO(), cacheKey).Int() // if countUserRefresh >= 2 { // response.Ok("目前已是最新数据", c) // return // } // countUserRefresh += 1 // now := time.Now() // today := time.Date(now.Year(), now.Month(), now.Day(), 23, 59, 59, 0, time.Local) // sub := today.Sub(now) // _ = global.Redis.SetEX(context.TODO(), cacheKey, countUserRefresh, sub) //} // 图表信息校验 chartInfo, err := chartInfoModel.GetChartInfoById(chartInfoId) if err != nil { if err == utils.ErrNoRow { response.Fail("图表已被删除,无需刷新", c) return } response.FailMsg("刷新失败", "刷新失败, Err:"+err.Error(), c) return } // 刷新图表 if err = future_goodServ.FutureGoodChartInfoRefresh(chartInfo.ChartInfoId); err != nil { errContent := fmt.Sprint("ErrMsg: 刷新图表关联指标信息失败, " + err.Error()) if global.CONFIG.Serve.RunMode == "release" { go alarm_msg.SendAlarmMsg("刷新图表报错"+time.Now().Format("2006-01-02 15:04:05")+";Err:"+errContent, 3) //go services.SendEmail("弘则研报小程序-release-刷新图表报错", errContent, utils.EmailSendToUsers) } else { global.LOG.Info(errContent) } } //清除图表缓存 { key := utils.HZ_CHART_LIB_DETAIL + chartInfo.UniqueCode _ = global.Redis.Del(context.TODO(), key) } response.OkData("刷新成功", "", c) } // FutureGoodChartInfoSave 编辑商品价格图表信息 // @Tags 图库模块 // @Summary 编辑图表信息 // @Description 编辑图表信息 // @Security ApiKeyAuth // @Param Authorization header string true "Bearer 31a165baebe6dec616b1f8f3207b4273" // @Accept json // @Product json // @Param data body chartInfoModel.SaveChartInfoReq true "请求参数" // @Success 200 {string} string "操作成功" // @failure 400 {string} string "操作失败" // @Router /my_chart/editChartInfo [post] func FutureGoodChartInfoSave(c *gin.Context) { // 参数校验 var req chartInfoModel.SaveChartInfoReq if c.ShouldBind(&req) != nil { response.Fail("参数异常", c) return } if req.ChartInfoId <= 0 { response.Fail("参数异常", c) return } // 操作权限校验 userInfo := user.GetInfoByClaims(c) ok, adminInfo, err := user.GetAdminByUserInfo(userInfo) if err != nil { response.Fail("操作人信息有误", c) return } if !ok { response.Fail("非内部人员无权进行操作", c) return } // 图表信息校验 chartItem, err := chartInfoModel.GetChartInfoById(req.ChartInfoId) if err != nil { if err == utils.ErrNoRow { response.Fail("图表已被删除,请刷新页面!", c) return } response.FailMsg("操作失败", "获取图表信息失败, Err:"+err.Error(), c) return } if chartItem.Source != 2 { response.Fail("该图不是商品价格曲线图", c) return } chartItem.LeftMin = req.LeftMin chartItem.LeftMax = req.LeftMax err = chartItem.Update([]string{"LeftMin", "LeftMax"}) if err != nil { response.FailMsg("保存失败", "保存失败,Err:"+err.Error(), c) return } // 清除图表缓存 cacheKey := utils.HZ_CHART_LIB_DETAIL + chartItem.UniqueCode _ = global.Redis.Del(context.TODO(), cacheKey) // 新增操作日志 { chartLog := new(chart_info_log.ChartInfoLog) chartLog.ChartName = chartItem.ChartName chartLog.ChartInfoId = req.ChartInfoId chartLog.ChartClassifyId = chartItem.ChartClassifyId chartLog.SysUserId = int(adminInfo.AdminID) chartLog.SysUserRealName = adminInfo.RealName chartLog.UniqueCode = chartItem.UniqueCode chartLog.CreateTime = time.Now() bodyBytes, _ := ioutil.ReadAll(c.Request.Body) chartLog.Content = string(bodyBytes) chartLog.Status = "修改配置项" chartLog.Method = c.Request.URL.String() go chartLog.Create() } response.OkData("操作成功", "", c) } // getCorrelationChartInfoDetail 获取相关性图表详情 func getCorrelationChartInfoDetail(chartInfo *chartInfoModel.ChartInfoView, myChartClassifyId int, userInfo user.UserInfo) (resp *chart_info.ChartInfoDetailResp, isOk bool, msg, errMsg string) { resp = new(chart_info.ChartInfoDetailResp) // 获取图表信息 //var err error chartInfoId := chartInfo.ChartInfoId chartInfo.ChartSource = "弘则研究" startDate := chartInfo.StartDate endDate := chartInfo.EndDate // 兼容日期错误 { if strings.Count(startDate, "-") == 1 { startDate = startDate + "-01" } if strings.Count(endDate, "-") == 1 { endDate = endDate + "-01" } } // 相关性图表信息 correlationChart := new(chart_info_correlation.ChartInfoCorrelation) if e := correlationChart.GetItemById(chartInfoId); e != nil { msg = "获取失败" errMsg = "获取图表相关性信息失败, Err:" + e.Error() return } // 获取指标信息 edbInfoMappingA, e := chartEdbMappingModel.GetChartEdbMappingByEdbInfoId(correlationChart.EdbInfoIdFirst) if e != nil { msg = "获取失败" errMsg = "获取相关性图表, A指标mapping信息失败, Err:" + e.Error() return } edbInfoMappingB, e := chartEdbMappingModel.GetChartEdbMappingByEdbInfoId(correlationChart.EdbInfoIdSecond) if e != nil { msg = "获取失败" errMsg = "获取相关性图表, B指标mapping信息失败, Err:" + e.Error() return } var dataResp interface{} // 绘图数据返回(目前是滚动相关性的图) var xEdbIdValue []int var xDateTimeValue []string var yDataList []chart_info.YData switch chartInfo.Source { case utils.CHART_SOURCE_CORRELATION: // 相关性图 moveUnitDays, ok := utils.FrequencyDaysMap[correlationChart.CalculateUnit] if !ok { msg = "错误的分析周期" errMsg = "相关性图表数据有误" return } startDate := time.Now().AddDate(0, 0, -correlationChart.CalculateValue*moveUnitDays).Format(utils.FormatDate) endDate := time.Now().Format(utils.FormatDate) xEdbIdValue, yDataList, e = correlation.GetChartDataByEdbInfo(edbInfoMappingA, edbInfoMappingB, correlationChart.LeadValue, correlationChart.LeadUnit, startDate, endDate) if e != nil { msg = "获取失败" errMsg = "获取相关性图表, 图表计算值失败, Err:" + e.Error() return } case utils.CHART_SOURCE_ROLLING_CORRELATION: // 滚动相关性图 multipleGraphConfigChartMapping, e := multiple_graph_config_chart_mapping.GetMultipleGraphConfigChartMappingByChartId(chartInfo.ChartInfoId) if e != nil { msg = "获取失败" errMsg = "获取滚动相关性图表的配置信息失败, Err:" + e.Error() return } baseChartMultipleGraphConfigChartMapping, e := multiple_graph_config_chart_mapping.GetMultipleGraphConfigChartMappingByIdAndSource(multipleGraphConfigChartMapping.MultipleGraphConfigID, 2) if e != nil { msg = "获取失败" errMsg = "获取相关性图表的配置信息失败, Err:" + e.Error() return } baseChartCorrelationChart := new(chart_info_correlation.ChartInfoCorrelation) if e := baseChartCorrelationChart.GetItemById(baseChartMultipleGraphConfigChartMapping.ChartInfoID); e != nil { msg = "获取失败" errMsg = "获取基础相关性图表信息失败, Err:" + e.Error() return } moveUnitDays, ok := utils.FrequencyDaysMap[baseChartCorrelationChart.CalculateUnit] if !ok { msg = "错误的分析周期" errMsg = "错误的分析周期" return } startDate := time.Now().AddDate(0, 0, -baseChartCorrelationChart.CalculateValue*moveUnitDays).Format(utils.FormatDate) endDate := time.Now().Format(utils.FormatDate) xDateTimeValue, yDataList, e = correlation.GetRollingCorrelationChartDataByEdbInfo(edbInfoMappingA, edbInfoMappingB, correlationChart.LeadValue, correlationChart.LeadUnit, correlationChart.CalculateValue, correlationChart.CalculateUnit, startDate, endDate) dataResp = chart_info.RollingCorrelationChartDataResp{ XDateTimeValue: xDateTimeValue, YDataList: yDataList, } } // 完善指标信息 edbList, e := correlation.GetChartEdbInfoFormat(chartInfo.ChartInfoId, edbInfoMappingA, edbInfoMappingB) if e != nil { msg = "获取失败" errMsg = "获取相关性图表, 完善指标信息失败, Err:" + e.Error() return } baseEdbInfo := edbList[0] //现货指标 chartInfo.UnitEn = baseEdbInfo.UnitEn correlationInfo := new(chart_info.CorrelationInfo) correlationInfo.LeadValue = correlationChart.LeadValue correlationInfo.LeadUnit = correlationChart.LeadUnit correlationInfo.StartDate = correlationChart.StartDate.Format(utils.FormatDate) correlationInfo.EndDate = correlationChart.EndDate.Format(utils.FormatDate) correlationInfo.LeadValue = correlationChart.LeadValue correlationInfo.EdbInfoIdFirst = correlationChart.EdbInfoIdFirst correlationInfo.EdbInfoIdSecond = correlationChart.EdbInfoIdSecond // 访问记录-仅普通用户记录 ok, _, _ := user.GetAdminByUserInfo(userInfo) if !ok { go chart.SaveChartVisitLog(userInfo, chartInfo, myChartClassifyId) } // 用户是否有收藏该图表 { ob := new(yb_my_chart.YbMyChart) cond := `user_id = ? AND chart_info_id = ?` pars := make([]interface{}, 0) pars = append(pars, userInfo.UserID, chartInfo.ChartInfoId) exists, e := ob.FetchByCondition(cond, pars) if e != nil && e != utils.ErrNoRow { msg = `操作失败` errMsg = "获取用户图表失败, Err: " + e.Error() return } myChartInfo := new(responseModel.MyChartItem) if exists != nil && exists.MyChartID > 0 { myChartInfo.MyChartID = exists.MyChartID myChartInfo.MyChartClassifyID = exists.MyChartClassifyID myChartInfo.ChartInfoID = exists.ChartInfoID myChartInfo.ChartName = exists.ChartName myChartInfo.UniqueCode = exists.UniqueCode myChartInfo.ChartImage = exists.ChartImage myChartInfo.UserID = exists.UserID myChartInfo.ReportID = exists.ReportID myChartInfo.ReportChapterID = exists.ReportChapterID myChartInfo.CreateTime = utils.TimeTransferString(utils.FormatDateTime, exists.CreateTime) } resp.MyChartInfo = myChartInfo } resp.ChartInfo = chartInfo resp.EdbInfoList = edbList resp.XEdbIdValue = xEdbIdValue resp.YDataList = yDataList resp.CorrelationChartInfo = correlationInfo resp.DataResp = dataResp isOk = true return } // RefreshCorrelationChartInfo 刷新相关性图表信息 // @Tags 图库模块 // @Summary 刷新图表信息 // @Description 刷新图表信息 // @Security ApiKeyAuth // @Param Authorization header string true "Bearer 31a165baebe6dec616b1f8f3207b4273" // @Accept json // @Product json // @Param data body chartInfoModel.SaveChartInfoReq true "请求参数" // @Success 200 {string} string "操作成功" // @failure 400 {string} string "操作失败" // @Router /my_chart/correlation/refreshChartInfo [post] func RefreshCorrelationChartInfo(c *gin.Context) { // 参数校验 var req chartInfoModel.RefreshChartInfoReq if c.ShouldBind(&req) != nil { response.Fail("参数异常", c) return } chartInfoId := req.ChartInfoId if chartInfoId == 0 { response.Fail("参数有误", c) return } userInfo := user.GetInfoByClaims(c) ok, _, err := user.GetAdminByUserInfo(userInfo) if err != nil { response.FailMsg("刷新失败", "RefreshChartInfo-获取系统用户信息失败"+err.Error(), c) return } if !ok { // 普通用户刷新频率限制-每个用户/图/天/2次 cacheKey := utils.HZ_CHART_LIB_DETAIL + "YB_REFRESH_LIMIT_" + strconv.Itoa(chartInfoId) + "_" + strconv.Itoa(int(userInfo.UserID)) countUserRefresh, _ := global.Redis.Get(context.TODO(), cacheKey).Int() if countUserRefresh >= 2 { response.Ok("目前已是最新数据", c) return } countUserRefresh += 1 now := time.Now() today := time.Date(now.Year(), now.Month(), now.Day(), 23, 59, 59, 0, time.Local) sub := today.Sub(now) _ = global.Redis.SetEX(context.TODO(), cacheKey, countUserRefresh, sub) } // 图表信息校验 chartInfo, err := chartInfoModel.GetChartInfoById(chartInfoId) if err != nil { if err == utils.ErrNoRow { response.Fail("图表已被删除,无需刷新", c) return } response.FailMsg("刷新失败", "刷新失败, Err:"+err.Error(), c) return } // 刷新图表 _ = correlation.ChartInfoRefresh(chartInfo.ChartInfoId) //清除图表缓存 { key := utils.HZ_CHART_LIB_DETAIL + chartInfo.UniqueCode _ = global.Redis.Del(context.TODO(), key) } response.OkData("刷新成功", "", c) }