Browse Source

新增国能物产数据接口和相关功能

- 添加国能物产数据新增、刷新和同步增量指标的接口
- 实现从桥接服务获取国能物产数据的功能
- 优化数据源验证逻辑,从静态映射改为动态查询
- 新增数据刷新和同步功能,支持增量数据的获取和更新
- 重构了原有的粮油商务网数据获取逻辑,提高了代码复用性
Roc 6 months ago
parent
commit
573df8a5b1

+ 255 - 0
controllers/base_from_gn.go

@@ -0,0 +1,255 @@
+package controllers
+
+import (
+	"encoding/json"
+	"eta_gn/eta_index_lib/logic"
+	"eta_gn/eta_index_lib/models"
+	"eta_gn/eta_index_lib/services"
+	"eta_gn/eta_index_lib/utils"
+	"fmt"
+	"strconv"
+	"time"
+)
+
+// GnController
+type GnController struct {
+	BaseAuthController
+}
+
+// Add
+// @Title 国能物产-新增指标接口
+// @Description  新增指标接口
+// @Success 200 {object} models.AddEdbInfoReq
+// @router /add [post]
+func (this *GnController) Add() {
+	br := new(models.BaseResponse).Init()
+	var cacheKey string
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		_ = utils.Rc.Delete(cacheKey)
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req models.AddEdbInfoReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "参数解析异常, err: " + e.Error()
+		return
+	}
+	if req.EdbCode == "" {
+		br.Msg = "请输入指标编码"
+		br.ErrMsg = "指标编码为空"
+		return
+	}
+	if req.Source <= 0 {
+		br.Msg = "请输入指标来源"
+		br.ErrMsg = "指标来源为空"
+		return
+	}
+
+	// 加锁
+	cacheKey = utils.CACHE_EDB_DATA_ADD + strconv.Itoa(req.Source) + "_" + req.EdbCode
+	if utils.Rc.IsExist(cacheKey) {
+		br.Ret = 501
+		br.Success = true
+		br.Msg = "系统处理中,请稍后重试"
+		return
+	}
+	utils.Rc.SetNX(cacheKey, 1, 1*time.Minute)
+	defer func() {
+		_ = utils.Rc.Delete(cacheKey)
+	}()
+
+	// 校验数据源
+	sourceItem := models.GetEdbSourceBySourceId(req.Source)
+	if sourceItem == nil {
+		br.Msg = "数据源有误"
+		br.ErrMsg = fmt.Sprintf("数据源有误, Source: %d", req.Source)
+		return
+	}
+
+	// 从桥接服务获取指标和数据
+	var params models.BridgeJiaYueIndexDataParams
+	params.IndexCode = req.EdbCode
+	params.SourceExtend = sourceItem.SourceExtend
+	params.StartDate = utils.BASE_START_DATE
+	params.EndDate = utils.BASE_END_DATE
+	params.IndexCodeRequired = sourceItem.EdbCodeRequired
+	indexData, e := services.GetJiaYueIndexDataFromBridge(params)
+	if e != nil {
+		br.Msg = "获取指标失败"
+		br.ErrMsg = "获取指标数据失败, Err: " + e.Error()
+		return
+	}
+	if indexData.Id <= 0 {
+		br.Msg = "指标不存在"
+		br.Success = true
+		return
+	}
+
+	// 新增指标数据
+	e = models.AddEdbDataFromJiaYue(sourceItem.TableName1, req.EdbCode, indexData.IndexData)
+	if e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "新增指标数据失败, Err: " + e.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+// Refresh
+// @Title 国能物产-刷新指标接口
+// @Description 刷新指标接口
+// @Success 200 {object} models.RefreshEdbInfoReq
+// @router /refresh [post]
+func (this *GnController) Refresh() {
+	br := new(models.BaseResponse).Init()
+	var cacheKey string
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req models.RefreshEdbInfoReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.EdbCode == "" {
+		br.Msg = "请输入指标编码!"
+		br.ErrMsg = "请输入指标编码,指标编码为空"
+		return
+	}
+	if req.EdbInfoId <= 0 {
+		br.Msg = "请输入指标ID!"
+		br.ErrMsg = "请输入指标ID"
+		return
+	}
+	if req.Source <= 0 {
+		br.Msg = "请输入指标来源"
+		br.ErrMsg = "指标来源为空"
+		return
+	}
+	startDate := req.StartDate
+	if startDate == "" {
+		startDate = utils.BASE_START_DATE
+	}
+
+	// 加锁
+	cacheKey = utils.CACHE_EDB_DATA_REFRESH + strconv.Itoa(req.Source) + "_" + req.EdbCode
+	if utils.Rc.IsExist(cacheKey) {
+		br.Ret = 501
+		br.Success = true
+		br.Msg = "系统处理中,请稍后重试"
+		return
+	}
+	utils.Rc.SetNX(cacheKey, 1, 1*time.Minute)
+	defer func() {
+		_ = utils.Rc.Delete(cacheKey)
+	}()
+
+	// 校验指标和数据源
+	edbInfo, e := models.GetEdbInfoById(req.EdbInfoId)
+	if e != nil {
+		br.Msg = "指标信息有误"
+		br.ErrMsg = "查询指标信息失败, Err: " + e.Error()
+		return
+	}
+	sourceItem := models.GetEdbSourceBySourceId(req.Source)
+	if sourceItem == nil {
+		br.Msg = "数据源有误"
+		br.ErrMsg = fmt.Sprintf("数据源有误, Source: %d", req.Source)
+		return
+	}
+
+	// 从桥接服务获取指标和数据
+	var params models.BridgeGnIndexDataParams
+	params.IndexCode = edbInfo.OriginalEdbCode
+	params.StartDate = startDate
+	params.EndDate = utils.BASE_END_DATE
+	indexDataList, e := services.GetGnIndexDataListFromBridge(params)
+	if e != nil {
+		br.Msg = "获取指标失败"
+		br.ErrMsg = "获取指标数据失败, Err: " + e.Error()
+		return
+	}
+
+	// 刷新指标数据
+	e = models.RefreshEdbDataFromGn(req.Source, edbInfo.SubSource, req.EdbInfoId, sourceItem.TableName1, req.EdbCode, startDate, indexDataList)
+	if e != nil {
+		br.Msg = "刷新失败"
+		br.ErrMsg = "刷新国能指标失败, Err: " + e.Error()
+		return
+	}
+
+	// 更新指标最大最小值
+	e, errMsg := models.UnifiedModifyEdbInfoMaxAndMinInfo(edbInfo)
+	if e != nil {
+		br.Msg = errMsg
+		br.ErrMsg = e.Error()
+		return
+	}
+
+	// 更新ES
+	go logic.UpdateEs(edbInfo.EdbInfoId)
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+// SyncNewIndex
+// @Title 国能物产-同步增量指标
+// @Description  同步增量指标
+// @Success 200 {object} models.AddEdbInfoReq
+// @router /sync_new_index [post]
+func (this *GnController) SyncNewIndex() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	// 从桥接服务获取增量指标
+	newIndexes, e := services.GetJiaYueNewIndexFromBridge()
+	if e != nil {
+		br.Msg = "同步增量指标失败"
+		br.ErrMsg = "同步增量指标失败, Err: " + e.Error()
+		return
+	}
+	if len(newIndexes) == 0 {
+		utils.FileLog.Info("无增量指标同步")
+		return
+	}
+
+	// 获取指标目录
+	indexMenus, e := services.GetJiaYueMenuListFromBridge()
+	if e != nil {
+		br.Msg = "获取指标目录失败"
+		br.ErrMsg = "获取指标目录失败, Err: " + e.Error()
+		return
+	}
+
+	go func() {
+		for _, v := range newIndexes {
+			// 错误信息在FileLog中这边不做返回
+			_ = services.SyncJiaYueNewIndex(v, indexMenus)
+		}
+	}()
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}

+ 2 - 2
controllers/base_from_jiayue.go

@@ -63,7 +63,7 @@ func (this *JiaYueController) Add() {
 	}()
 
 	// 校验数据源
-	sourceItem := models.EdbSourceIdMap[req.Source]
+	sourceItem := models.GetEdbSourceBySourceId(req.Source)
 	if sourceItem == nil {
 		br.Msg = "数据源有误"
 		br.ErrMsg = fmt.Sprintf("数据源有误, Source: %d", req.Source)
@@ -164,7 +164,7 @@ func (this *JiaYueController) Refresh() {
 		br.ErrMsg = "查询指标信息失败, Err: " + e.Error()
 		return
 	}
-	sourceItem := models.EdbSourceIdMap[req.Source]
+	sourceItem := models.GetEdbSourceBySourceId(req.Source)
 	if sourceItem == nil {
 		br.Msg = "数据源有误"
 		br.ErrMsg = fmt.Sprintf("数据源有误, Source: %d", req.Source)

+ 162 - 0
models/base_from_gn.go

@@ -0,0 +1,162 @@
+package models
+
+import (
+	"eta_gn/eta_index_lib/global"
+	"eta_gn/eta_index_lib/utils"
+	"fmt"
+	"strconv"
+	"strings"
+	"time"
+)
+
+// BridgeGnIndexDataParams 桥接服务-获取国能指标数据入参
+type BridgeGnIndexDataParams struct {
+	IndexCode string `json:"index_code" form:"index_code" description:"指标编码"`
+	StartDate string `json:"start_date" form:"start_date" description:"开始日期"`
+	EndDate   string `json:"end_date" form:"end_date" description:"结束日期"`
+}
+
+// BridgeGnIndexAndData 桥接服务-国能指标和数据
+type BridgeGnIndexAndData struct {
+	Val        float64 `json:"val"`
+	DataTime   string  `json:"data_time"`
+	UpdateTime string  `json:"update_time"`
+}
+
+// BridgeGnResultIndexData 桥接服务-获取国能指标数据响应体
+type BridgeGnResultIndexData struct {
+	Code int                    `json:"code" description:"状态码"`
+	Msg  string                 `json:"msg" description:"提示信息"`
+	Data []BridgeGnIndexAndData `json:"data" description:"返回数据"`
+}
+
+// RefreshEdbDataFromGn
+// @Description: 刷新国能指标数据
+// @param source
+// @param subSource
+// @param edbInfoId
+// @param tableName
+// @param edbCode
+// @param startDate
+// @param dataList
+// @return err
+func RefreshEdbDataFromGn(source, subSource, edbInfoId int, tableName, edbCode, startDate string, dataList []BridgeGnIndexAndData) (err error) {
+	if source <= 0 {
+		err = fmt.Errorf("指标来源有误")
+		return
+	}
+	if edbInfoId <= 0 {
+		err = fmt.Errorf("指标ID有误")
+		return
+	}
+	if tableName == "" {
+		err = fmt.Errorf("数据表名为空")
+		return
+	}
+
+	// 真实数据的最大日期, 插入规则配置的日期
+	var realDataMaxDate, edbDataInsertConfigDate time.Time
+	var edbDataInsertConfig *EdbDataInsertConfig
+	var isFindConfigDateRealData bool //是否找到配置日期的实际数据的值
+	{
+		conf, e := GetEdbDataInsertConfigByEdbId(edbInfoId)
+		if e != nil && e.Error() != utils.ErrNoRow() {
+			return
+		}
+		edbDataInsertConfig = conf
+		if edbDataInsertConfig != nil {
+			edbDataInsertConfigDate = edbDataInsertConfig.Date
+		}
+	}
+
+	// 获取已有数据
+	cond := ` AND edb_info_id = ?`
+	pars := make([]interface{}, 0)
+	pars = append(pars, edbInfoId)
+	var startDateTime time.Time
+	if startDate != "" {
+		cond += ` AND data_time >= ?`
+		pars = append(pars, startDate)
+		startDateTime, _ = time.ParseInLocation(utils.FormatDate, startDate, time.Local)
+	}
+	existList, e := GetEdbDataByCondition(source, subSource, cond, pars)
+	if e != nil {
+		err = fmt.Errorf("获取指标已有数据失败, Err: %s", e.Error())
+		return
+	}
+	existMap := make(map[string]*EdbInfoSearchData)
+	for _, v := range existList {
+		existMap[v.DataTime] = v
+	}
+
+	// 比对数据
+	hasNew := false
+	strEdbInfoId := strconv.Itoa(edbInfoId)
+	addExists := make(map[string]bool)
+	sqlInsert := fmt.Sprintf(`INSERT INTO %s(edb_info_id, edb_code, data_time, value, create_time, modify_time, data_timestamp) VALUES `, tableName)
+	for _, v := range dataList {
+		currDataTime, tmpErr := time.ParseInLocation(utils.FormatDate, v.DataTime, time.Local)
+		if tmpErr != nil {
+			err = tmpErr
+			return
+		}
+		val := utils.SubFloatToString(v.Val, 30)
+		stamp := fmt.Sprint(currDataTime.UnixMilli())
+		dataTime := currDataTime.Format(utils.FormatDate)
+
+		// 如果传入的开始时间是空的, 且当前数据日期早于传入的开始日期, 那么需要判断下当前日期的数据是否存在
+		if !startDateTime.IsZero() && currDataTime.Before(startDateTime) {
+			t, e := GetEdbDataByDate(source, subSource, edbCode, dataTime)
+			if e == nil && t != nil {
+				existMap[t.DataTime] = t
+			}
+		}
+
+		// 下面代码主要目的是处理掉手动插入的数据判断
+		{
+			if realDataMaxDate.IsZero() || currDataTime.After(realDataMaxDate) {
+				realDataMaxDate = currDataTime
+			}
+			if edbDataInsertConfigDate.IsZero() || currDataTime.Equal(edbDataInsertConfigDate) {
+				isFindConfigDateRealData = true
+			}
+		}
+
+		// 新增数据
+		exist, ok := existMap[dataTime]
+		if !ok {
+			// 不在历史数据中且与新增中的数据不重复
+			if _, o := addExists[dataTime]; !o {
+				hasNew = true
+				sqlInsert += GetAddSql(strEdbInfoId, edbCode, dataTime, stamp, val)
+				addExists[dataTime] = true
+			}
+			continue
+		}
+
+		// 更新数据
+		if exist != nil && utils.SubFloatToString(exist.Value, 30) != val {
+			if e = ModifyEdbDataById(source, subSource, exist.EdbDataId, val); e != nil {
+				err = fmt.Errorf("modify edb data err: %s", e.Error())
+				return
+			}
+		}
+	}
+
+	// 处理手工数据补充的配置
+	HandleConfigInsertEdbData(realDataMaxDate, edbDataInsertConfig, edbInfoId, source, subSource, existMap, isFindConfigDateRealData)
+
+	// 执行新增
+	if !hasNew {
+		return
+	}
+	//o := orm.NewOrm()
+	sqlInsert = strings.TrimRight(sqlInsert, ",")
+	//_, e = o.Raw(sqlInsert).Exec()
+	e = global.DEFAULT_DmSQL.Exec(sqlInsert).Error
+	if e != nil {
+		err = fmt.Errorf("insert edb data err: %s", e.Error())
+		return
+	}
+	return
+}

+ 1 - 1
models/edb_data_table.go

@@ -173,7 +173,7 @@ func GetEdbDataTableName(source, subSource int) (tableName string) {
 	case utils.DATA_SOURCE_LY: // 粮油商务网->91
 		tableName = "edb_data_ly"
 	default:
-		edbSource := EdbSourceIdMap[source]
+		edbSource := GetEdbSourceBySourceId(source)
 		if edbSource != nil {
 			tableName = edbSource.TableName1
 		}

+ 3 - 2
models/edb_info.go

@@ -66,6 +66,7 @@ type EdbInfo struct {
 	IndicatorCode    string    `gorm:"column:indicator_code" description:"指标代码"`
 	StockCode        string    `gorm:"column:stock_code" description:"证券代码"`
 	Extra            string    `gorm:"column:extra" description:"指标的额外配置"`
+	OriginalEdbCode  string    `description:"指标原始编码"`
 }
 
 func (e *EdbInfo) Add() (err error) {
@@ -231,7 +232,7 @@ func ModifyEdbInfoNameSource(edbNameSource string, edbInfoId int) (err error) {
 
 // GetEdbInfoById 根据指标id获取指标信息
 func GetEdbInfoById(edbInfoId int) (item *EdbInfo, err error) {
-	sql := ` SELECT * FROM edb_info WHERE edb_info_id=? `
+	sql := ` SELECT * FROM edb_info WHERE edb_info_id = ? `
 	err = global.DEFAULT_DmSQL.Raw(sql, edbInfoId).First(&item).Error
 	if err != nil {
 		return
@@ -1550,7 +1551,7 @@ func EdbInfoAdd(req *AddEdbInfoParams, serverUrl string, sysUserId int, sysUserR
 
 	sourceName, ok := sourceNameMap[source]
 	if !ok {
-		edbSource := EdbSourceIdMap[source]
+		edbSource := GetEdbSourceBySourceId(source)
 		if edbSource != nil {
 			sourceName = edbSource.SourceName
 		}

+ 34 - 1
models/edb_source.go

@@ -25,7 +25,7 @@ type EdbSource struct {
 	EdbCodeRequired  int    `gorm:"column:edb_code_required;not null;default:0" description:"指标编码是否必填: 0-否; 1-是"`
 }
 
-// 获取表名
+// TableName 获取表名
 func (e *EdbSource) TableName() string {
 	return "edb_source"
 }
@@ -75,3 +75,36 @@ func InitEdbSource() {
 		}
 	}
 }
+
+// GetEdbSourceItemsSourceId
+// @Description: 根据来源id获取指标来源
+// @param sourceId
+// @return item
+// @return err
+func GetEdbSourceItemsSourceId(sourceId int) (item *EdbSource, err error) {
+	sql := `SELECT * FROM edb_source WHERE 1=1 AND edb_source_id = ? `
+	err = global.DEFAULT_DmSQL.Raw(sql, sourceId).First(&item).Error
+
+	return
+}
+
+// GetEdbSourceBySourceId
+// @Description: 根据来源id获取指标来源
+// @param sourceId
+// @return sourceItem
+func GetEdbSourceBySourceId(sourceId int) (sourceItem *EdbSource) {
+	sourceItem, ok := EdbSourceIdMap[sourceId]
+	if !ok {
+		item, err := GetEdbSourceItemsSourceId(sourceId)
+		if err != nil {
+			return
+		}
+		if item.EdbSourceId > 0 {
+			sourceItem = item
+			// 写入到内存中
+			EdbSourceIdMap[sourceId] = sourceItem
+		}
+	}
+
+	return
+}

+ 52 - 25
routers/commentsRouter.go

@@ -844,6 +844,33 @@ func init() {
 			Filters:          nil,
 			Params:           nil})
 
+	beego.GlobalControllerRouter["eta_gn/eta_index_lib/controllers:GnController"] = append(beego.GlobalControllerRouter["eta_gn/eta_index_lib/controllers:GnController"],
+		beego.ControllerComments{
+			Method:           "Add",
+			Router:           `/add`,
+			AllowHTTPMethods: []string{"post"},
+			MethodParams:     param.Make(),
+			Filters:          nil,
+			Params:           nil})
+
+	beego.GlobalControllerRouter["eta_gn/eta_index_lib/controllers:GnController"] = append(beego.GlobalControllerRouter["eta_gn/eta_index_lib/controllers:GnController"],
+		beego.ControllerComments{
+			Method:           "Refresh",
+			Router:           `/refresh`,
+			AllowHTTPMethods: []string{"post"},
+			MethodParams:     param.Make(),
+			Filters:          nil,
+			Params:           nil})
+
+	beego.GlobalControllerRouter["eta_gn/eta_index_lib/controllers:GnController"] = append(beego.GlobalControllerRouter["eta_gn/eta_index_lib/controllers:GnController"],
+		beego.ControllerComments{
+			Method:           "SyncNewIndex",
+			Router:           `/sync_new_index`,
+			AllowHTTPMethods: []string{"post"},
+			MethodParams:     param.Make(),
+			Filters:          nil,
+			Params:           nil})
+
 	beego.GlobalControllerRouter["eta_gn/eta_index_lib/controllers:GoogleTravelController"] = append(beego.GlobalControllerRouter["eta_gn/eta_index_lib/controllers:GoogleTravelController"],
 		beego.ControllerComments{
 			Method:           "Add",
@@ -1745,30 +1772,30 @@ func init() {
 			Params:           nil})
 
 	beego.GlobalControllerRouter["eta_gn/eta_index_lib/controllers:YongyiController"] = append(beego.GlobalControllerRouter["eta_gn/eta_index_lib/controllers:YongyiController"],
-        beego.ControllerComments{
-            Method: "Refresh",
-            Router: `/refresh`,
-            AllowHTTPMethods: []string{"post"},
-            MethodParams: param.Make(),
-            Filters: nil,
-            Params: nil})
-
-    beego.GlobalControllerRouter["eta_gn/eta_index_lib/controllers:ZzController"] = append(beego.GlobalControllerRouter["eta_gn/eta_index_lib/controllers:ZzController"],
-        beego.ControllerComments{
-            Method: "Add",
-            Router: `/add`,
-            AllowHTTPMethods: []string{"post"},
-            MethodParams: param.Make(),
-            Filters: nil,
-            Params: nil})
-
-    beego.GlobalControllerRouter["eta_gn/eta_index_lib/controllers:ZzController"] = append(beego.GlobalControllerRouter["eta_gn/eta_index_lib/controllers:ZzController"],
-        beego.ControllerComments{
-            Method: "Refresh",
-            Router: `/refresh`,
-            AllowHTTPMethods: []string{"post"},
-            MethodParams: param.Make(),
-            Filters: nil,
-            Params: nil})
+		beego.ControllerComments{
+			Method:           "Refresh",
+			Router:           `/refresh`,
+			AllowHTTPMethods: []string{"post"},
+			MethodParams:     param.Make(),
+			Filters:          nil,
+			Params:           nil})
+
+	beego.GlobalControllerRouter["eta_gn/eta_index_lib/controllers:ZzController"] = append(beego.GlobalControllerRouter["eta_gn/eta_index_lib/controllers:ZzController"],
+		beego.ControllerComments{
+			Method:           "Add",
+			Router:           `/add`,
+			AllowHTTPMethods: []string{"post"},
+			MethodParams:     param.Make(),
+			Filters:          nil,
+			Params:           nil})
+
+	beego.GlobalControllerRouter["eta_gn/eta_index_lib/controllers:ZzController"] = append(beego.GlobalControllerRouter["eta_gn/eta_index_lib/controllers:ZzController"],
+		beego.ControllerComments{
+			Method:           "Refresh",
+			Router:           `/refresh`,
+			AllowHTTPMethods: []string{"post"},
+			MethodParams:     param.Make(),
+			Filters:          nil,
+			Params:           nil})
 
 }

+ 5 - 0
routers/router.go

@@ -212,6 +212,11 @@ func init() {
 				&controllers.JiaYueController{},
 			),
 		),
+		beego.NSNamespace("/gn_index",
+			beego.NSInclude(
+				&controllers.GnController{},
+			),
+		),
 		beego.NSNamespace("/edb_stat",
 			beego.NSInclude(
 				&controllers.EdbInfoStatController{},

+ 252 - 0
services/base_from_gn.go

@@ -0,0 +1,252 @@
+package services
+
+import (
+	"encoding/json"
+	"eta_gn/eta_index_lib/models"
+	"eta_gn/eta_index_lib/services/alarm_msg"
+	"eta_gn/eta_index_lib/utils"
+	"fmt"
+	"io"
+	"net/http"
+	"strings"
+)
+
+var (
+	BridgeApiGnIndexDataUrl = "/api/index_data/gn/edb/data/list" // 获取指标数据API
+	BridgeApiGnNewIndexUrl  = "/api/index_data/gn/new_index"     // 获取增量指标API
+	BridgeApiGnMenuListUrl  = "/api/index_data/gn/menu_list"     // 获取指标目录API
+)
+
+// GetGnIndexDataListFromBridge
+// @Description: 从桥接服务获取指标数据
+// @param param
+// @return indexDataList
+// @return err
+func GetGnIndexDataListFromBridge(param models.BridgeGnIndexDataParams) (indexDataList []models.BridgeGnIndexAndData, err error) {
+	defer func() {
+		if err != nil {
+			b, _ := json.Marshal(param)
+			tips := fmt.Sprintf("桥接服务-获取国能指标数据失败, err: %s, params: %s", err.Error(), string(b))
+			utils.FileLog.Info(tips)
+			go alarm_msg.SendAlarmMsg(tips, 3)
+		}
+	}()
+
+	url := fmt.Sprint(utils.EtaBridgeUrl, BridgeApiGnIndexDataUrl)
+	data, e := json.Marshal(param)
+	if e != nil {
+		err = fmt.Errorf("data json marshal err: %s", e.Error())
+		return
+	}
+	body := io.NopCloser(strings.NewReader(string(data)))
+	client := &http.Client{}
+	req, e := http.NewRequest("POST", url, body)
+	if e != nil {
+		err = fmt.Errorf("http create request err: %s", e.Error())
+		return
+	}
+
+	checkToken := utils.MD5(utils.EtaBridgeAppNameEn + utils.EtaBridgeMd5Key)
+	contentType := "application/json;charset=utf-8"
+	req.Header.Set("Content-Type", contentType)
+	req.Header.Set("Authorization", checkToken)
+	resp, e := client.Do(req)
+	if e != nil {
+		err = fmt.Errorf("http client do err: %s", e.Error())
+		return
+	}
+	defer func() {
+		_ = resp.Body.Close()
+	}()
+	b, e := io.ReadAll(resp.Body)
+	if e != nil {
+		err = fmt.Errorf("resp body read err: %s", e.Error())
+		return
+	}
+	if len(b) == 0 {
+		err = fmt.Errorf("resp body is empty")
+		return
+	}
+
+	fmt.Println(string(b))
+	// 生产环境解密
+	if utils.RunMode == "release" {
+		str := string(b)
+		str = strings.Trim(str, `"`)
+		b = utils.DesBase64Decrypt([]byte(str), utils.EtaBridgeDesKey)
+	}
+
+	result := new(models.BridgeGnResultIndexData)
+	if e = json.Unmarshal(b, &result); e != nil {
+		err = fmt.Errorf("result unmarshal err: %s\nresult: %s", e.Error(), string(b))
+		return
+	}
+	if result.Code != 200 {
+		err = fmt.Errorf("result: %s", string(b))
+		return
+	}
+	indexDataList = result.Data
+
+	return
+}
+
+// GetGnNewIndexFromBridge 从桥接服务获取增量指标
+func GetGnNewIndexFromBridge() (indexData []models.BridgeJiaYueIndexAndData, err error) {
+	defer func() {
+		if err != nil {
+			tips := fmt.Sprintf("桥接服务-获取国能增量指标失败, err: %s", err.Error())
+			utils.FileLog.Info(tips)
+			go alarm_msg.SendAlarmMsg(tips, 3)
+		}
+	}()
+
+	url := fmt.Sprint(utils.EtaBridgeUrl, BridgeApiGnNewIndexUrl)
+	body := io.NopCloser(strings.NewReader(""))
+	client := &http.Client{}
+	req, e := http.NewRequest("POST", url, body)
+	if e != nil {
+		err = fmt.Errorf("http create request err: %s", e.Error())
+		return
+	}
+
+	checkToken := utils.MD5(utils.EtaBridgeAppNameEn + utils.EtaBridgeMd5Key)
+	contentType := "application/json;charset=utf-8"
+	req.Header.Set("Content-Type", contentType)
+	req.Header.Set("Authorization", checkToken)
+	resp, e := client.Do(req)
+	if e != nil {
+		err = fmt.Errorf("http client do err: %s", e.Error())
+		return
+	}
+	defer func() {
+		_ = resp.Body.Close()
+	}()
+	b, e := io.ReadAll(resp.Body)
+	if e != nil {
+		err = fmt.Errorf("resp body read err: %s", e.Error())
+		return
+	}
+	if len(b) == 0 {
+		err = fmt.Errorf("resp body is empty")
+		return
+	}
+	// 生产环境解密
+	if utils.RunMode == "release" {
+		str := string(b)
+		str = strings.Trim(str, `"`)
+		b = utils.DesBase64Decrypt([]byte(str), utils.EtaBridgeDesKey)
+	}
+
+	result := new(models.BridgeJiaYueResultNewIndexData)
+	if e = json.Unmarshal(b, &result); e != nil {
+		err = fmt.Errorf("result unmarshal err: %s\nresult: %s", e.Error(), string(b))
+		return
+	}
+	if result.Code != 200 {
+		err = fmt.Errorf("result: %s", string(b))
+		return
+	}
+	indexData = result.Data
+	return
+}
+
+// GetGnMenuListFromBridge 从桥接服务获取指标目录列表
+func GetGnMenuListFromBridge() (indexData []models.BridgeJiaYueIndexMenuData, err error) {
+	defer func() {
+		if err != nil {
+			tips := fmt.Sprintf("桥接服务-获取国能增量指标失败, err: %s", err.Error())
+			utils.FileLog.Info(tips)
+			go alarm_msg.SendAlarmMsg(tips, 3)
+		}
+	}()
+
+	url := fmt.Sprint(utils.EtaBridgeUrl, BridgeApiGnMenuListUrl)
+	body := io.NopCloser(strings.NewReader(""))
+
+	client := &http.Client{}
+	req, e := http.NewRequest("POST", url, body)
+	if e != nil {
+		err = fmt.Errorf("http create request err: %s", e.Error())
+		return
+	}
+
+	checkToken := utils.MD5(utils.EtaBridgeAppNameEn + utils.EtaBridgeMd5Key)
+	contentType := "application/json;charset=utf-8"
+	req.Header.Set("Content-Type", contentType)
+	req.Header.Set("Authorization", checkToken)
+	resp, e := client.Do(req)
+	if e != nil {
+		err = fmt.Errorf("http client do err: %s", e.Error())
+		return
+	}
+	defer func() {
+		_ = resp.Body.Close()
+	}()
+	b, e := io.ReadAll(resp.Body)
+	if e != nil {
+		err = fmt.Errorf("resp body read err: %s", e.Error())
+		return
+	}
+	if len(b) == 0 {
+		err = fmt.Errorf("resp body is empty")
+		return
+	}
+	// 生产环境解密
+	if utils.RunMode == "release" {
+		str := string(b)
+		str = strings.Trim(str, `"`)
+		b = utils.DesBase64Decrypt([]byte(str), utils.EtaBridgeDesKey)
+	}
+
+	result := new(models.BridgeJiaYueResultMenuListData)
+	if e = json.Unmarshal(b, &result); e != nil {
+		err = fmt.Errorf("result unmarshal err: %s\nresult: %s", e.Error(), string(b))
+		return
+	}
+	if result.Code != 200 {
+		err = fmt.Errorf("result: %s", string(b))
+		return
+	}
+	indexData = result.Data
+	return
+}
+
+// TransGnFrequency 频度转换
+func TransGnFrequency(origin string) string {
+	mapping := map[string]string{
+		"日":   "日度",
+		"周":   "周度",
+		"旬":   "旬度",
+		"半月":  "旬度",
+		"月":   "月度",
+		"季":   "季度",
+		"半年":  "半年度",
+		"年":   "年度",
+		"日度":  "日度",
+		"周度":  "周度",
+		"旬度":  "旬度",
+		"月度":  "月度",
+		"季度":  "季度",
+		"半年度": "半年度",
+		"年度":  "年度",
+	}
+	return mapping[origin]
+}
+
+// GetGnParentMenusByMenu 获取指定目录的父级目录
+func GetGnParentMenusByMenu(menu models.BridgeJiaYueIndexMenuData, menus []models.BridgeJiaYueIndexMenuData, level int) (results []models.BridgeJiaYueIndexMenuWithLevel) {
+	results = make([]models.BridgeJiaYueIndexMenuWithLevel, 0)
+	for _, m := range menus {
+		if menu.ParentId == m.Id {
+			results = append(results, models.BridgeJiaYueIndexMenuWithLevel{
+				Level: level,
+				Menu:  m,
+			})
+			ps := GetGnParentMenusByMenu(m, menus, level+1)
+			if len(ps) > 0 {
+				results = append(results, ps...)
+			}
+		}
+	}
+	return
+}

+ 1 - 1
services/base_from_jiayue.go

@@ -223,7 +223,7 @@ func SyncJiaYueNewIndex(item models.BridgeJiaYueIndexAndData, menus []models.Bri
 		utils.FileLog.Info(fmt.Sprintf("指标来源ID有误, 忽略同步, sourceId: %d; sourceType: %s", sourceId, item.SourceType))
 		return
 	}
-	edbSource := models.EdbSourceIdMap[sourceId]
+	edbSource := models.GetEdbSourceBySourceId(sourceId)
 	if edbSource == nil {
 		utils.FileLog.Info(fmt.Sprintf("指标来源有误, sourceId: %d", sourceId))
 		return