Bläddra i källkod

Merge branch 'feature/eta1.9.1_edb_refresh' into debug

xyxie 9 månader sedan
förälder
incheckning
aa009cc2f5

+ 13 - 0
models/business_conf.go

@@ -165,3 +165,16 @@ func UpdateBusinessConfMulti(items []BusinessConfUpdate) (err error) {
 	}
 	return
 }
+
+func (m *BusinessConf) GetItemByConfKey(key string) (item *BusinessConf, err error) {
+	o := orm.NewOrmUsingDB("eta")
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE conf_key = ? LIMIT 1`, m.TableName())
+	err = o.Raw(sql, key).QueryRow(&item)
+	return
+}
+
+type EdbStopRefreshRule struct {
+	IsOpen            int `description:"是否开启自动禁用1,开启,0未开启"`
+	BaseIndexStopDays int `description:"数据源间隔天数未加入指标库则停用"`
+	EdbStopDays       int `description:"指标库间隔天数未引用则停用"`
+}

+ 27 - 1
models/data_manage/base_from_mysteel_chemical_index.go

@@ -1,6 +1,9 @@
 package data_manage
 
-import "github.com/beego/beego/v2/client/orm"
+import (
+	"eta/eta_task/utils"
+	"github.com/beego/beego/v2/client/orm"
+)
 
 type BaseFromMysteelChemicalIndexItem struct {
 	BaseFromMysteelChemicalIndexId    int32   `json:"base_from_mysteel_chemical_index_id"`
@@ -47,3 +50,26 @@ func GetBaseFromMysteelChemicalIndexItemByCode(edbCode string) (item *BaseFromMy
 
 	return
 }
+
+// GetRefreshBaseFromMysteelChemicalIndexItemByCreateTime 获取正常刷新的钢联化工指标
+func GetRefreshBaseFromMysteelChemicalIndexItemByCreateTime(endDate string, startPage, pageSize int) (items []*BaseFromMysteelChemicalIndexItem, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT * FROM base_from_mysteel_chemical_index WHERE is_stop = 0 and create_time < ? Limit ?,?`
+	_, err = o.Raw(sql, endDate, startPage, pageSize).QueryRows(&items)
+	return
+}
+
+// GetCountRefreshBaseFromMysteelChemicalIndexItemByCreateTime 获取正常刷新的钢联化工指标
+func GetCountRefreshBaseFromMysteelChemicalIndexItemByCreateTime(endDate string) (total int64, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT count(*) FROM base_from_mysteel_chemical_index WHERE is_stop = 0 and create_time < ?`
+	err = o.Raw(sql, endDate).QueryRow(&total)
+	return
+}
+
+func SetStopRefreshMysteelChemicalIndex(ids []int32) (err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` UPDATE base_from_mysteel_chemical_index SET is_stop = 1 WHERE base_from_mysteel_chemical_index_id IN (` + utils.GetOrmInReplace(len(ids)) + `) and is_stop=0`
+	_, err = o.Raw(sql, ids).Exec()
+	return
+}

+ 70 - 0
models/data_manage/business_sys_interaction_log.go

@@ -0,0 +1,70 @@
+package data_manage
+
+import (
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+// BusinessSysInteractionLog 商家系统交互记录表
+type BusinessSysInteractionLog struct {
+	ID             uint32    `orm:"column(id);pk" gorm:"primaryKey;column:id;type:int(10) unsigned;not null" json:"-"`
+	InteractionKey string    `gorm:"unique;column:interaction_key;type:varchar(128);not null;default:''" json:"interactionKey"` // 记录Key
+	InteractionVal string    `gorm:"column:interaction_val;type:text;default:null" json:"interactionVal"`                       // 记录值
+	Remark         string    `gorm:"column:remark;type:varchar(128);not null;default:''" json:"remark"`                         // 备注
+	ModifyTime     time.Time `gorm:"column:modify_time;type:datetime;default:null" json:"modifyTime"`                           // 修改日期
+	CreateTime     time.Time `gorm:"column:create_time;type:datetime;default:null" json:"createTime"`                           // 创建时间
+}
+
+// TableName get sql table name.获取数据库表名
+func (m *BusinessSysInteractionLog) TableName() string {
+	return "business_sys_interaction_log"
+}
+
+// BusinessSysInteractionLogColumns get sql column name.获取数据库列名
+var BusinessSysInteractionLogColumns = struct {
+	ID             string
+	InteractionKey string
+	InteractionVal string
+	Remark         string
+	ModifyTime     string
+	CreateTime     string
+}{
+	ID:             "id",
+	InteractionKey: "interaction_key",
+	InteractionVal: "interaction_val",
+	Remark:         "remark",
+	ModifyTime:     "modify_time",
+	CreateTime:     "create_time",
+}
+
+// Create 添加数据
+func (m *BusinessSysInteractionLog) Create() (err error) {
+	o := orm.NewOrm()
+	id, err := o.Insert(m)
+	if err != nil {
+		return
+	}
+	m.ID = uint32(id)
+
+	return
+}
+
+// Update 更新数据
+func (m *BusinessSysInteractionLog) Update(cols []string) (err error) {
+	o := orm.NewOrm()
+	_, err = o.Update(m, cols...)
+
+	return
+}
+
+var BinlogFileNameKey = "binlog_filename"            // binlog文件名
+var BinlogPositionKey = "binlog_binlog_position"     // binlog位置
+var CrmIndexLastUpdateTime = "crm_index_update_time" // crm数据
+
+// GetBusinessSysInteractionLogByKey 根据记录key获取数据
+func GetBusinessSysInteractionLogByKey(key string) (item *BusinessSysInteractionLog, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT * FROM business_sys_interaction_log WHERE 1=1 AND interaction_key = ? LIMIT 1`
+	err = o.Raw(sql, key).QueryRow(&item)
+	return
+}

+ 48 - 0
models/data_manage/chart_edb_mapping.go

@@ -0,0 +1,48 @@
+package data_manage
+
+import (
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+type ChartEdbMapping struct {
+	ChartEdbMappingId int       `orm:"column(chart_edb_mapping_id);pk"`
+	ChartInfoId       int       `description:"图表id"`
+	EdbInfoId         int       `description:"指标id"`
+	CreateTime        time.Time `description:"创建时间"`
+	ModifyTime        time.Time `description:"修改时间"`
+	UniqueCode        string    `description:"唯一编码"`
+	MaxData           float64   `description:"上限"`
+	MinData           float64   `description:"下限"`
+	IsOrder           bool      `description:"true:正序,false:逆序"`
+	IsAxis            int       `description:"true:左轴,false:右轴"`
+	EdbInfoType       int       `description:"true:标准指标,false:领先指标"`
+	LeadValue         int       `description:"领先值"`
+	LeadUnit          string    `description:"领先单位"`
+	ChartStyle        string    `description:"图表类型"`
+	ChartColor        string    `description:"颜色"`
+	PredictChartColor string    `description:"预测数据的颜色"`
+	ChartWidth        float64   `description:"线条大小"`
+	Source            int       `description:"1:ETA图库;2:商品价格曲线"`
+	EdbAliasName      string    `description:"中文别名"`
+	IsConvert         int       `description:"是否数据转换 0不转 1转"`
+	ConvertType       int       `description:"数据转换类型 1乘 2除 3对数"`
+	ConvertValue      float64   `description:"数据转换值"`
+	ConvertUnit       string    `description:"数据转换单位"`
+	ConvertEnUnit     string    `description:"数据转换单位"`
+}
+
+func GetChartEdbMappingTotal() (total int, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT COUNT(1) AS count FROM chart_edb_mapping `
+	err = o.Raw(sql).QueryRow(&total)
+	return
+}
+
+func GetChartEdbMappingList(startSize, pageSize int) (items []*ChartEdbMapping, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT * FROM chart_edb_mapping WHERE 1=1 `
+	sql += " LIMIT ?,? "
+	_, err = o.Raw(sql, startSize, pageSize).QueryRows(&items)
+	return
+}

+ 10 - 0
models/data_manage/chart_info.go

@@ -1,6 +1,7 @@
 package data_manage
 
 import (
+	"eta/eta_task/utils"
 	"github.com/beego/beego/v2/client/orm"
 	"time"
 )
@@ -26,6 +27,7 @@ type ChartInfo struct {
 	ChartImage      string `description:"图表图片"`
 	Sort            int    `description:"排序字段,数字越小越排前面"`
 	EdbEndDate      string `description:"指标最后更新日期"`
+	Source          int    `description:"1:ETA图库;2:商品价格曲线"`
 }
 
 func GetAllChartInfo() (list []*ChartInfo, err error) {
@@ -51,3 +53,11 @@ func ModifyChartInfoEdbEndDate(chartInfoId int, edbEndDate string) (err error) {
 	_, err = o.Raw(sql, edbEndDate, chartInfoId).Exec()
 	return
 }
+
+// 根据chart_info_id数组获取图表信息
+func GetChartInfoByChartInfoIds(chartInfoIds []int) (list []*ChartInfo, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT * FROM chart_info  WHERE chart_info_id IN (` + utils.GetOrmInReplace(len(chartInfoIds)) + `) `
+	_, err = o.Raw(sql, chartInfoIds).QueryRows(&list)
+	return
+}

+ 34 - 0
models/data_manage/cross_variety/chart_info_cross_variety.go

@@ -0,0 +1,34 @@
+package cross_variety
+
+import (
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+// ChartInfoCrossVariety
+// @Description: 跨品种分析配置表
+type ChartInfoCrossVariety struct {
+	Id             int       `orm:"column(id);pk"`
+	ChartInfoId    int       `description:"图表id"`
+	ChartXTagId    int       `description:"X轴的标签ID"`
+	ChartYTagId    int       `description:"X轴的标签ID"`
+	CalculateValue int       `description:"计算窗口"`
+	CalculateUnit  string    `description:"计算频度"`
+	ModifyTime     time.Time `description:"修改时间"`
+	CreateTime     time.Time `description:"创建时间"`
+}
+
+func GetChartInfoCrossVarietyList(startSize, pageSize int) (items []*ChartInfoCrossVariety, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT * FROM chart_info_cross_variety WHERE 1=1 `
+	sql += " LIMIT ?,? "
+	_, err = o.Raw(sql, startSize, pageSize).QueryRows(&items)
+	return
+}
+
+func GetChartInfoCrossVarietyTotal() (total int, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT count(*) FROM chart_info_cross_variety`
+	err = o.Raw(sql).QueryRow(&total)
+	return
+}

+ 27 - 0
models/data_manage/cross_variety/chart_tag_variety.go

@@ -0,0 +1,27 @@
+package cross_variety
+
+import (
+	"eta/eta_task/utils"
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+// ChartTagVariety
+// @Description: chart_tag_variety 图表标签品种关系表
+type ChartTagVariety struct {
+	Id                        int       `orm:"column(id);pk"`
+	ChartTagId                int       `description:"标签id"`
+	ChartVarietyId            int       `description:"品种id"`
+	EdbInfoId                 int       `description:"指标id"`
+	LastUpdateSysUserId       int       `description:"最后一次操作人"`
+	LastUpdateSysUserRealName string    `description:"最后一次操作人真实姓名"`
+	ModifyTime                time.Time `description:"修改时间"`
+	CreateTime                time.Time `description:"创建时间"`
+}
+
+func GetChartTagVarietyEdbInfoIdsByTagIds(chartTagIds []int) (items []*ChartTagVariety, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT * FROM chart_tag_variety WHERE chart_tag_id in (` + utils.GetOrmInReplace(len(chartTagIds)) + `)`
+	_, err = o.Raw(sql, chartTagIds).QueryRows(&items)
+	return
+}

+ 82 - 0
models/data_manage/edb_info.go

@@ -2,6 +2,7 @@ package data_manage
 
 import (
 	"errors"
+	"eta/eta_task/utils"
 	"fmt"
 	"github.com/beego/beego/v2/client/orm"
 	"strconv"
@@ -29,6 +30,8 @@ type EdbInfo struct {
 	MaxValue         float64 `description:"指标最大值"`
 	CalculateFormula string  `description:"计算公式"`
 	NoUpdate         int8    `description:"是否停止更新,0:继续更新;1:停止更新"`
+	EdbInfoType      int     `description:"指标类型,0:普通指标,1:预测指标"`
+	EdbType          int     `description:"指标类型:1:基础指标,2:计算指标"`
 }
 
 type EdbInfoList struct {
@@ -282,3 +285,82 @@ func GetEdbInfoMaxModifyTime(source, subSource int, edbCode string) (modifyTime
 
 	return
 }
+
+func GetEdbInfoPageByCondition(condition string, pars []interface{}, startPage, pageSize int) (item []*EdbInfoList, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT * FROM edb_info WHERE 1=1 `
+	if condition != "" {
+		sql += condition
+	}
+	sql += ` LIMIT ?,? `
+	_, err = o.Raw(sql, pars, startPage, pageSize).QueryRows(&item)
+	return
+}
+
+func GetEdbInfoCountByCondition(condition string, pars []interface{}) (total int64, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT count(*) FROM edb_info WHERE 1=1 `
+	if condition != "" {
+		sql += condition
+	}
+	err = o.Raw(sql, pars).QueryRow(&total)
+	return
+}
+
+func ModifyEdbUpdateStatus(edbIdList []int, indexCodeList []string, calculateEdbInfoIds []int) (err error) {
+	idNum := len(edbIdList)
+	if idNum <= 0 {
+		return
+	}
+	o, err := orm.NewOrmUsingDB("data").Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = o.Rollback()
+			return
+		}
+		_ = o.Commit()
+	}()
+
+	// 更改指标的更新状态
+	sql := ` UPDATE edb_info SET no_update = 1 WHERE source in (?, ?) AND edb_info_id IN (` + utils.GetOrmInReplace(idNum) + `) AND  no_update = 0`
+	_, err = o.Raw(sql, utils.DATA_SOURCE_MYSTEEL_CHEMICAL, utils.DATA_SOURCE_WIND, edbIdList).Exec()
+	if err != nil {
+		return
+	}
+
+	// 更改钢联化工指标更新状态
+	if len(indexCodeList) > 0 {
+		// 更改数据源的更新状态
+		sql = ` UPDATE base_from_mysteel_chemical_index SET is_stop = 1 WHERE index_code IN (` + utils.GetOrmInReplace(len(indexCodeList)) + `) and is_stop=0`
+		_, err = o.Raw(sql, indexCodeList).Exec()
+		if err != nil {
+			return
+		}
+	}
+
+	// 更新相关的计算指标状态
+	if len(calculateEdbInfoIds) > 0 {
+		// 批量更新相关联的指标ID
+		sql = ` UPDATE edb_info SET no_update = 1 WHERE edb_info_id IN (` + utils.GetOrmInReplace(len(calculateEdbInfoIds)) + `) AND  no_update = 0`
+		_, err = o.Raw(sql, calculateEdbInfoIds).Exec()
+		if err != nil {
+			return
+		}
+	}
+	return
+}
+
+// GetEdbInfoByIdList 根据指标id集合 获取 指标列表
+func GetEdbInfoByIdList(edbInfoIdList []int) (items []*EdbInfo, err error) {
+	num := len(edbInfoIdList)
+	if num <= 0 {
+		return
+	}
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT * FROM edb_info WHERE edb_info_id in (` + utils.GetOrmInReplace(num) + `) `
+	_, err = o.Raw(sql, edbInfoIdList).QueryRows(&items)
+	return
+}

+ 57 - 0
models/data_manage/edb_info_calculate_mapping.go

@@ -1,6 +1,7 @@
 package data_manage
 
 import (
+	"eta/eta_task/utils"
 	"fmt"
 	"github.com/beego/beego/v2/client/orm"
 	"time"
@@ -111,3 +112,59 @@ func GetEdbInfoCalculateMappingDetail(edbInfoId int) (item *EdbInfoCalculateMapp
 	err = o.Raw(sql, edbInfoId).QueryRow(&item)
 	return
 }
+
+// GetAllCalculateEdbIdsByEdbInfoIds 所依赖计算指标
+func GetAllCalculateEdbIdsByEdbInfoIds(edbInfoIds []int) (edbIds []int, err error) {
+	o := orm.NewOrmUsingDB("data")
+	msql := ` SELECT edb_info_id FROM edb_info_calculate_mapping WHERE from_edb_info_id in (` + utils.GetOrmInReplace(len(edbInfoIds)) + `)  GROUP BY edb_info_id `
+	_, err = o.Raw(msql, edbInfoIds).QueryRows(&edbIds)
+	if err != nil {
+		return
+	}
+	return
+}
+
+// EdbInfoCalculateMappingInfo
+// @Description: 计算指标与基础指标关系表
+type EdbInfoCalculateMappingInfo struct {
+	EdbInfoCalculateMappingId int       `orm:"column(edb_info_calculate_mapping_id);pk"`
+	EdbInfoId                 int       `description:"计算指标id"`
+	Source                    int       `description:"计算指标来源"`
+	SourceName                string    `description:"计算指标来源名称"`
+	EdbCode                   string    `description:"计算指标编码"`
+	FromEdbInfoId             int       `description:"基础指标id"`
+	FromEdbCode               string    `description:"基础指标编码"`
+	FromEdbName               string    `description:"基础指标名称"`
+	FromSource                int       `description:"基础指标来源"`
+	FromSourceName            string    `description:"基础指标来源名称"`
+	MoveValue                 int       `description:"领先值"`
+	FromTag                   string    `description:"来源指标标签"`
+	Sort                      int       `description:"计算指标名称排序"`
+	CreateTime                time.Time `description:"创建时间"`
+	ModifyTime                time.Time `description:"修改时间"`
+	FromEdbType               int       `description:"来源指标类型:1:基础指标,2:计算指标"`
+	FromEdbInfoType           int       `description:"来源指标类型: 0-基础指标; 1-预测指标"`
+	FromClassifyId            int       `description:"来源指标分类ID"`
+	FromUniqueCode            string    `description:"来源指标唯一编码"`
+	NoUpdate                  int8      `description:"是否停止更新,0:继续更新;1:停止更新"`
+}
+
+// GetEdbInfoCalculateMappingListByEdbInfoId 根据生成的指标id获取来源的指标id列表
+func GetEdbInfoCalculateMappingListByEdbInfoId(edbInfoId int) (items []*EdbInfoCalculateMappingInfo, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT a.*,b.edb_type as from_edb_type,b.edb_info_type as from_edb_info_type, b.unique_code AS from_unique_code, b.classify_id AS from_classify_id,b.no_update FROM edb_info_calculate_mapping AS a
+			INNER JOIN edb_info AS b ON a.from_edb_info_id=b.edb_info_id
+			WHERE a.edb_info_id=? `
+	_, err = o.Raw(sql, edbInfoId).QueryRows(&items)
+	return
+}
+
+// GetEdbInfoCalculateMappingListByEdbInfoIds 根据生成的指标id获取来源的指标id列表
+func GetEdbInfoCalculateMappingListByEdbInfoIds(edbInfoIds []int) (items []*EdbInfoCalculateMappingInfo, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT a.*,b.edb_type as from_edb_type,b.edb_info_type as from_edb_info_type, b.unique_code AS from_unique_code, b.classify_id AS from_classify_id,b.no_update FROM edb_info_calculate_mapping AS a
+			INNER JOIN edb_info AS b ON a.from_edb_info_id=b.edb_info_id
+			WHERE a.edb_info_id in (` + utils.GetOrmInReplace(len(edbInfoIds)) + `) `
+	_, err = o.Raw(sql, edbInfoIds).QueryRows(&items)
+	return
+}

+ 96 - 0
models/data_manage/edb_info_relation.go

@@ -0,0 +1,96 @@
+package data_manage
+
+import (
+	"eta/eta_task/utils"
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+type EdbInfoRelation struct {
+	EdbInfoRelationId  int       `orm:"column(edb_info_relation_id);pk"`
+	EdbInfoId          int       `description:"指标id"`
+	Source             int       `description:"来源:1:同花顺,2:wind,3:彭博,4:指标运算,5:累计值转月,6:同比值,7:同差值,8:N数值移动平均计算,9:手工指标,10:隆众"`
+	EdbName            string    `description:"指标名称"`
+	EdbCode            string    `description:"指标编码"`
+	ReferObjectId      int       `description:"引用对象ID(图表ID,ETA逻辑ID等)"`
+	ReferObjectType    int       `description:"引用对象ID类型(1.图表,2.ETA逻辑)"`
+	ReferObjectSubType int       `description:"引用对象子类"`
+	CreateTime         time.Time `description:"创建时间"`
+	ModifyTime         time.Time `description:"修改时间"`
+	RelationTime       time.Time `description:"引用时间"`
+	RelationType       int       `description:"引用类型,0:直接饮用,1间接引用"`
+	RootEdbInfoId      int       `description:"间接引用时,关联的直接引用的指标ID"`
+	ChildEdbInfoId     int       `description:"间接引用时,计算指标直接关联的指标ID"`
+	RelationCode       string    `description:"引用标识"`
+	ParentRelationId   int       `description:"间接引用关联的直接引用的ID"`
+}
+
+func (e *EdbInfoRelation) TableName() string {
+	return "edb_info_relation"
+}
+
+func AddEdbInfoRelationMulti(relationList []*EdbInfoRelation) (err error) {
+	o, err := orm.NewOrmUsingDB("data").Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = o.Rollback()
+			return
+		}
+		_ = o.Commit()
+	}()
+
+	relationCodesMap := make(map[string]struct{}, 0)
+	if len(relationList) > 0 {
+		for _, relation := range relationList {
+			if relation.RelationType == 1 {
+				relationCodesMap[relation.RelationCode] = struct{}{}
+			}
+		}
+		_, err = o.InsertMulti(len(relationList), relationList)
+		if err != nil {
+			return
+		}
+	}
+	if len(relationList) > 0 {
+		// 更新间接引用指标的关联ID
+		relationCodes := make([]string, 0)
+		for relationCode := range relationCodesMap {
+			relationCodes = append(relationCodes, relationCode)
+		}
+		if len(relationCodes) > 0 {
+			sql := ` UPDATE edb_info_relation e1  
+JOIN edb_info_relation e2 ON e1.relation_code = e2.relation_code   
+SET e1.parent_relation_id = e2.edb_info_relation_id  
+WHERE  
+    e1.relation_type = 1   
+    AND e2.relation_type = 0 AND e1.parent_relation_id !=e2.edb_info_relation_id AND e1.relation_code in (` + utils.GetOrmInReplace(len(relationCodes)) + `)`
+			_, err = o.Raw(sql, relationCodes).Exec()
+			if err != nil {
+				return
+			}
+		}
+	}
+	return
+}
+
+// GetEdbInfoRelationByEdbInfoIds 查询引用的指标ID
+func GetEdbInfoRelationByEdbInfoIds(edbInfoIds []int) (edbIds []int, err error) {
+	o := orm.NewOrmUsingDB("data")
+	msql := ` SELECT edb_info_id FROM edb_info_relation WHERE edb_info_id in (` + utils.GetOrmInReplace(len(edbInfoIds)) + `)  GROUP BY edb_info_id `
+	_, err = o.Raw(msql, edbInfoIds).QueryRows(&edbIds)
+	if err != nil {
+		return
+	}
+	return
+}
+
+// GetEdbInfoRelationByReferObjectIds 查询引用的指标ID
+func GetEdbInfoRelationByReferObjectIds(referObjectIds []int, referObjectType int) (items []*EdbInfoRelation, err error) {
+	o := orm.NewOrmUsingDB("data")
+	msql := ` SELECT * FROM edb_info_relation WHERE refer_object_id in (` + utils.GetOrmInReplace(len(referObjectIds)) + `) AND refer_object_type=? AND relation_type=0`
+	_, err = o.Raw(msql, referObjectIds, referObjectType).QueryRows(&items)
+	return
+}

+ 35 - 0
models/data_manage/excel/excel_edb_mapping.go

@@ -0,0 +1,35 @@
+package excel
+
+import (
+	"eta/eta_task/utils"
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+// ExcelEdbMapping excel与指标的关系表
+type ExcelEdbMapping struct {
+	ExcelEdbMappingId int       `orm:"column(excel_edb_mapping_id);pk"`
+	ExcelInfoId       int       `description:"excel的id"`
+	Source            int       `description:"表格来源,1:excel插件的表格,2:自定义表格,3:混合表格,4:自定义分析,默认:1"`
+	EdbInfoId         int       `description:"计算指标id"`
+	CreateTime        time.Time `description:"创建时间"`
+	ModifyTime        time.Time `description:"修改时间"`
+}
+
+// GetExcelEdbMappingTotalBySource 根据表格类型获取总数
+func GetExcelEdbMappingTotalBySource(sources []int) (total int, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT count(*)  FROM excel_edb_mapping WHERE source in (` + utils.GetOrmInReplace(len(sources)) + `)`
+
+	err = o.Raw(sql, sources).QueryRow(&total)
+	return
+}
+
+// GetExcelEdbMappingListBySource 根据表格类型获取列表
+func GetExcelEdbMappingListBySource(sources []int, pageIndex, pageSize int) (items []*ExcelEdbMapping, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT *  FROM excel_edb_mapping WHERE source in (` + utils.GetOrmInReplace(len(sources)) + `) Limit ?,? `
+
+	_, err = o.Raw(sql, sources, pageIndex, pageSize).QueryRows(&items)
+	return
+}

+ 3 - 0
models/db.go

@@ -126,6 +126,9 @@ func initEdbDataTable() {
 		new(data_manage.BaseFromIcpiIndex),
 		new(data_manage.BaseFromIcpiClassify),
 		new(data_manage.BaseFromIcpiData),
+		new(data_manage.BusinessSysInteractionLog), // 商家系统交互记录表
+
+		new(data_manage.EdbInfoRelation), //指标引用关联表
 	)
 }
 

+ 117 - 0
models/fe_calendar/fe_calendar_matter.go

@@ -0,0 +1,117 @@
+package fe_calendar
+
+import (
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
+	"strings"
+	"time"
+)
+
+const (
+	MatterTypeFree    = 1 // 事项类型-自定义事项
+	MatterTypeEdb     = 2 // 事项类型-基础指标
+	MatterTypePredict = 3 // 事项类型-预测指标
+)
+
+// FeCalendarMatter 外汇日历-事项表
+type FeCalendarMatter struct {
+	FeCalendarMatterId  int       `orm:"column(fe_calendar_matter_id);pk" description:"事项ID"`
+	ChartPermissionId   int       `description:"品种ID"`
+	ChartPermissionName string    `description:"品种名称"`
+	MatterMonth         string    `description:"事项年月:格式2006-01"`
+	MatterDate          time.Time `description:"事项日期"`
+	Title               string    `description:"标题"`
+	MatterType          int       `description:"事项类型:1-自定义事项;2-基础指标;3-预测指标"`
+	EdbInfoId           int       `description:"指标ID"`
+	EdbUniqueCode       string    `description:"指标唯一编码"`
+	EdbCode             string    `description:"指标编码"`
+	FontColor           string    `description:"字体颜色"`
+	FillingColor        string    `description:"填充颜色"`
+	FontBold            int       `description:"字体加粗:0-否;1-是"`
+	Sort                int       `description:"排序"`
+	SysUserId           int       `description:"创建人ID"`
+	SysUserName         string    `description:"创建人姓名"`
+	CreateTime          time.Time `description:"创建时间"`
+	ModifyTime          time.Time `description:"更新时间"`
+}
+
+var FeCalendarMatterCols = struct {
+	FeCalendarMatterId  string
+	ChartPermissionId   string
+	ChartPermissionName string
+	MatterMonth         string
+	MatterDate          string
+	Title               string
+	MatterType          string
+	EdbInfoId           string
+	EdbUniqueCode       string
+	EdbCode             string
+	FontColor           string
+	FillingColor        string
+	FontBold            string
+	Sort                string
+	SysUserId           string
+	SysUserName         string
+	CreateTime          string
+	ModifyTime          string
+}{
+	FeCalendarMatterId:  "fe_calendar_matter_id",
+	ChartPermissionId:   "chart_permission_id",
+	ChartPermissionName: "chart_permission_name",
+	MatterMonth:         "matter_month",
+	MatterDate:          "matter_date",
+	Title:               "title",
+	MatterType:          "matter_type",
+	EdbInfoId:           "edb_info_id",
+	EdbUniqueCode:       "edb_unique_code",
+	EdbCode:             "edb_code",
+	FontColor:           "font_color",
+	FillingColor:        "filling_color",
+	FontBold:            "font_bold",
+	Sort:                "sort",
+	SysUserId:           "sys_user_id",
+	SysUserName:         "sys_user_name",
+	CreateTime:          "create_time",
+	ModifyTime:          "modify_time",
+}
+
+func (m *FeCalendarMatter) TableName() string {
+	return "fe_calendar_matter"
+}
+
+func (m *FeCalendarMatter) PrimaryId() string {
+	return FeCalendarMatterCols.FeCalendarMatterId
+}
+
+func (m *FeCalendarMatter) GetItemByCondition(condition string, pars []interface{}, orderRule string) (item *FeCalendarMatter, err error) {
+	o := orm.NewOrmUsingDB("data")
+	order := ``
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE 1=1 %s %s LIMIT 1`, m.TableName(), condition, order)
+	err = o.Raw(sql, pars).QueryRow(&item)
+	return
+}
+
+func (m *FeCalendarMatter) GetCountByCondition(condition string, pars []interface{}) (count int, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := fmt.Sprintf(`SELECT COUNT(1) FROM %s WHERE 1=1 %s`, m.TableName(), condition)
+	err = o.Raw(sql, pars).QueryRow(&count)
+	return
+}
+
+func (m *FeCalendarMatter) GetPageItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string, startSize, pageSize int) (items []*FeCalendarMatter, err error) {
+	o := orm.NewOrmUsingDB("data")
+	fields := strings.Join(fieldArr, ",")
+	if len(fieldArr) == 0 {
+		fields = `*`
+	}
+	order := fmt.Sprintf(`ORDER BY %s DESC`, FeCalendarMatterCols.CreateTime)
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT %s FROM %s WHERE 1=1 %s %s LIMIT ?,?`, fields, m.TableName(), condition, order)
+	_, err = o.Raw(sql, pars, startSize, pageSize).QueryRows(&items)
+	return
+}

+ 91 - 0
models/sandbox/sandbox.go

@@ -0,0 +1,91 @@
+package sandbox
+
+import (
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+// Sandbox 沙盘推演主表
+//type Sandbox struct {
+//	SandboxId           int       `orm:"column(sandbox_id);pk" description:"沙盘id"`
+//	Name                string    `description:"沙盘名称"`
+//	ChartPermissionId   int       `description:"品种id"`
+//	ChartPermissionName string    `description:"品种名称"`
+//	CurrVersion         int       `description:"当前版本"`
+//	Code                string    `description:"沙盘code"`
+//	Content             string    `description:"沙盘数据"`
+//	PicUrl              string    `description:"沙盘图片地址"`
+//	OpUserId            int       `description:"最近一次编辑操作的用户id"`
+//	OpUserName          string    `description:"最近一次编辑的用户名称(冗余字段,避免查表)"`
+//	IsDelete            int8      `description:"是否删除,0:未删除,1:已删除"`
+//	ModifyTime          time.Time `description:"修改时间"`
+//	CreateTime          time.Time `description:"创建时间"`
+//	SandboxClassifyId   int       `description:"分类id"`
+//	Sort                int       `description:"排序"`
+//}
+
+type Sandbox struct {
+	SandboxId         int       `orm:"column(sandbox_id);pk" description:"沙盘id"`
+	Name              string    `description:"沙盘名称"`
+	Code              string    `description:"沙盘code"`
+	Content           string    `description:"沙盘数据"`
+	MindmapData       string    `description:"思维导图数据"`
+	PicUrl            string    `description:"沙盘图片地址"`
+	SysUserId         int       `description:"作者id"`
+	SysUserName       string    `description:"作者名称"`
+	IsDelete          int8      `description:"是否删除,0:未删除,1:已删除"`
+	ModifyTime        time.Time `description:"修改时间"`
+	CreateTime        time.Time `description:"创建时间"`
+	SandboxClassifyId int       `description:"分类id"`
+	Sort              int       `description:"排序"`
+	Style             int       `description:"风格"`
+}
+
+func GetSandboxListByCondition(condition string, pars []interface{}, startSize, pageSize int) (item []*Sandbox, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT * FROM sandbox WHERE 1=1 `
+	if condition != "" {
+		sql += condition
+	}
+	sql += " ORDER BY create_time DESC LIMIT ?,? "
+	_, err = o.Raw(sql, pars, startSize, pageSize).QueryRows(&item)
+	return
+}
+
+func GetSandboxListCountByCondition(condition string, pars []interface{}) (count int, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT COUNT(1) AS count FROM sandbox WHERE 1=1 `
+	if condition != "" {
+		sql += condition
+	}
+	err = o.Raw(sql, pars).QueryRow(&count)
+	return
+}
+
+// ContentDataStruct 沙盘内容结构体
+type ContentDataStruct struct {
+	Cells []struct {
+		Data *NodeData `json:"data,omitempty"`
+	} `json:"cells"`
+}
+
+type NodeData struct {
+	LinkData []*LinkData `json:"linkData"`
+	LinkFold bool        `json:"linkFold"`
+}
+
+type LinkData struct {
+	RId          string       `json:"RId"`
+	Id           int          `json:"Id"`
+	Name         string       `json:"Name"`
+	Type         int          `json:"Type"`
+	Editing      bool         `json:"editing"`
+	DatabaseType int          `json:"databaseType"`
+	DetailParams DetailParams `json:"detailParams"`
+}
+
+type DetailParams struct {
+	Code       string `json:"code"`
+	Id         int    `json:"id"`
+	ClassifyId int    `json:"classifyId"`
+}

+ 6 - 3
services/data/edb_info.go

@@ -823,9 +823,12 @@ func RefreshDataFromLt(wg *sync.WaitGroup) (err error) {
 	errMsgList := make([]string, 0)
 	defer func() {
 		if len(errMsgList) > 0 {
-			fmt.Println("RefreshDataFromLt Err:", errMsgList)
-			go alarm_msg.SendAlarmMsg("RefreshDataFromLt ErrMsg:"+strings.Join(errMsgList, `<br/>`), 3)
+			tips := fmt.Sprintf("RefreshDataFromLt ErrMsg: %s", strings.Join(errMsgList, `<br/>`))
+			fmt.Println(tips)
+			utils.FileLog.Info(tips)
+			go alarm_msg.SendAlarmMsg(tips, 3)
 		}
+		utils.FileLog.Info("RefreshDataFromLt刷新结束")
 		wg.Done()
 	}()
 	var condition string
@@ -841,7 +844,7 @@ func RefreshDataFromLt(wg *sync.WaitGroup) (err error) {
 	for _, v := range items {
 		fmt.Println(v.EdbCode, v.Frequency, v.EndDate)
 		startDate := v.StartDate.Format(utils.FormatDate)
-		resp, err := RefreshEdbData(v.EdbInfoId, v.SubSource, v.Source, v.EdbCode, startDate)
+		resp, err := RefreshEdbData(v.EdbInfoId, v.Source, v.SubSource, v.EdbCode, startDate)
 		if err != nil {
 			errMsgList = append(errMsgList, "RefreshEdbData Err:"+err.Error())
 			continue

+ 13 - 8
services/data/future_good/future_good_edb_info.go

@@ -15,16 +15,15 @@ func RefreshFutureGoodDataFromThs() (err error) {
 	errMsgList := make([]string, 0)
 	defer func() {
 		if err != nil {
-			fmt.Println("RefreshDataFromThs Err:" + err.Error())
-			//go utils.SendEmail(utils.APPNAME+"【"+utils.RunMode+"】"+"失败提醒", "RefreshDataFromThs ErrMsg:"+err.Error(), utils.EmailSendToUsers)
-			go alarm_msg.SendAlarmMsg("RefreshDataFromThs ErrMsg:"+err.Error(), 3)
+			tips := fmt.Sprintf("RefreshFutureGoodDataFromThs Err: %v", err)
+			//fmt.Println(tips)
+			utils.FileLog.Info(tips)
+			go alarm_msg.SendAlarmMsg(tips, 3)
 		}
 		if len(errMsgList) > 0 {
-			go alarm_msg.SendAlarmMsg("部分商品数据刷新失败 ErrMsg:"+strings.Join(errMsgList, "/n"), 3)
-			//fmt.Println("总共",len(errMsgList),"条商品数据刷新失败:")
-			//for _,v:=range errMsgList{
-			//	fmt.Println(v)
-			//}
+			tips := fmt.Sprintf("RefreshFutureGoodDataFromThs部分商品刷新失败, ErrMsg: %s", strings.Join(errMsgList, "\n"))
+			utils.FileLog.Info(tips)
+			go alarm_msg.SendAlarmMsg(tips, 3)
 		}
 	}()
 	var condition string
@@ -43,7 +42,13 @@ func RefreshFutureGoodDataFromThs() (err error) {
 
 	lenList := len(list)
 	fmt.Println("总共", lenList, "条")
+
+	// 简单限制一下请求速度, 同花顺EDB函数限制为5/s
+	ticker := time.NewTicker(250 * time.Millisecond)
+	defer ticker.Stop()
 	for k, v := range list {
+		<-ticker.C
+
 		fmt.Println("剩余", lenList-k-1, "条")
 		fmt.Println("编码:", v.FutureGoodEdbCode, ";名称:", v.FutureGoodEdbName)
 		var startDateTime time.Time

+ 290 - 37
services/edb_refresh.go

@@ -2,6 +2,9 @@ package services
 
 import (
 	"context"
+	"encoding/json"
+	"eta/eta_task/models"
+	"eta/eta_task/models/data_manage"
 	"eta/eta_task/models/data_manage/edb_refresh"
 	"eta/eta_task/services/alarm_msg"
 	"eta/eta_task/services/data"
@@ -303,48 +306,103 @@ func BaseRefreshData(wg *sync.WaitGroup, source, subSource int, items []*edb_ref
 	// 是否从最开始的日期更新
 	var isRefreshByStartDate bool
 
-	for _, v := range items {
-		// 如果暂停更新,那就过滤
-		if v.NoUpdate == 1 {
-			continue
-		}
-		if v.DataRefreshNum > 0 {
-			dataRefreshNum = v.DataRefreshNum
-		}
+	if source != utils.DATA_SOURCE_THS {
+		for _, v := range items {
+			// 如果暂停更新,那就过滤
+			if v.NoUpdate == 1 {
+				continue
+			}
+			if v.DataRefreshNum > 0 {
+				dataRefreshNum = v.DataRefreshNum
+			}
 
-		startDate := ""
-		if isRefreshByStartDate {
-			startDate = v.StartDate.Format(utils.FormatDate)
-		} else {
-			if v.Frequency == "日度" {
-				startDate = v.EndDate.AddDate(0, 0, -dataRefreshNum).Format(utils.FormatDate)
-			} else if v.Frequency == "周度" {
-				startDate = v.EndDate.AddDate(0, 0, -(dataRefreshNum * 7)).Format(utils.FormatDate)
-			} else if v.Frequency == "旬度" {
-				startDate = v.EndDate.AddDate(0, 0, -(dataRefreshNum * 10)).Format(utils.FormatDate)
-			} else if v.Frequency == "月度" {
-				startDate = v.EndDate.AddDate(0, -dataRefreshNum, 0).Format(utils.FormatDate)
-			} else if v.Frequency == "季度" {
-				startDate = v.EndDate.AddDate(0, -dataRefreshNum*3, 0).Format(utils.FormatDate)
-			} else if v.Frequency == "半年度" {
-				startDate = v.EndDate.AddDate(0, -dataRefreshNum*6, 0).Format(utils.FormatDate)
-			} else if v.Frequency == "年度" {
-				startDate = v.EndDate.AddDate(-dataRefreshNum, 0, 0).Format(utils.FormatDate)
+			startDate := ""
+			if isRefreshByStartDate {
+				startDate = v.StartDate.Format(utils.FormatDate)
 			} else {
-				startDate = v.EndDate.AddDate(0, 0, -utils.DATA_REFRESH).Format(utils.FormatDate)
+				if v.Frequency == "日度" {
+					startDate = v.EndDate.AddDate(0, 0, -dataRefreshNum).Format(utils.FormatDate)
+				} else if v.Frequency == "周度" {
+					startDate = v.EndDate.AddDate(0, 0, -(dataRefreshNum * 7)).Format(utils.FormatDate)
+				} else if v.Frequency == "旬度" {
+					startDate = v.EndDate.AddDate(0, 0, -(dataRefreshNum * 10)).Format(utils.FormatDate)
+				} else if v.Frequency == "月度" {
+					startDate = v.EndDate.AddDate(0, -dataRefreshNum, 0).Format(utils.FormatDate)
+				} else if v.Frequency == "季度" {
+					startDate = v.EndDate.AddDate(0, -dataRefreshNum*3, 0).Format(utils.FormatDate)
+				} else if v.Frequency == "半年度" {
+					startDate = v.EndDate.AddDate(0, -dataRefreshNum*6, 0).Format(utils.FormatDate)
+				} else if v.Frequency == "年度" {
+					startDate = v.EndDate.AddDate(-dataRefreshNum, 0, 0).Format(utils.FormatDate)
+				} else {
+					startDate = v.EndDate.AddDate(0, 0, -utils.DATA_REFRESH).Format(utils.FormatDate)
+				}
 			}
-		}
-		fmt.Println(startDate)
+			fmt.Println(startDate)
 
-		// 数据更新
-		resp, tmpErr := data.RefreshEdbData(v.EdbInfoId, v.Source, v.SubSource, v.EdbCode, startDate)
-		if tmpErr != nil {
-			errMsgList = append(errMsgList, v.EdbCode+"RefreshEdbData Err:"+tmpErr.Error())
-			continue
+			// 数据更新
+			resp, tmpErr := data.RefreshEdbData(v.EdbInfoId, v.Source, v.SubSource, v.EdbCode, startDate)
+			if tmpErr != nil {
+				errMsgList = append(errMsgList, v.EdbCode+"RefreshEdbData Err:"+tmpErr.Error())
+				continue
+			}
+			if resp.Ret != 200 {
+				errMsgList = append(errMsgList, v.EdbCode+";RefreshEdbData Err:"+resp.Msg+";ErrMsg:"+resp.ErrMsg)
+				continue
+			}
 		}
-		if resp.Ret != 200 {
-			errMsgList = append(errMsgList, v.EdbCode+";RefreshEdbData Err:"+resp.Msg+";ErrMsg:"+resp.ErrMsg)
-			continue
+	}
+
+	// 同花顺控制速率, 每秒最多4次请求(同花顺EDB函数限制为5, 考虑到可能存在用户同时在使用, 这里批量刷新设置为4, 话说5确实是有点少了吧=_=!)
+	if source == utils.DATA_SOURCE_THS {
+		ticker := time.NewTicker(250 * time.Millisecond)
+		defer ticker.Stop()
+
+		for _, v := range items {
+			<-ticker.C
+
+			// 如果暂停更新,那就过滤
+			if v.NoUpdate == 1 {
+				continue
+			}
+			if v.DataRefreshNum > 0 {
+				dataRefreshNum = v.DataRefreshNum
+			}
+
+			startDate := ""
+			if isRefreshByStartDate {
+				startDate = v.StartDate.Format(utils.FormatDate)
+			} else {
+				if v.Frequency == "日度" {
+					startDate = v.EndDate.AddDate(0, 0, -dataRefreshNum).Format(utils.FormatDate)
+				} else if v.Frequency == "周度" {
+					startDate = v.EndDate.AddDate(0, 0, -(dataRefreshNum * 7)).Format(utils.FormatDate)
+				} else if v.Frequency == "旬度" {
+					startDate = v.EndDate.AddDate(0, 0, -(dataRefreshNum * 10)).Format(utils.FormatDate)
+				} else if v.Frequency == "月度" {
+					startDate = v.EndDate.AddDate(0, -dataRefreshNum, 0).Format(utils.FormatDate)
+				} else if v.Frequency == "季度" {
+					startDate = v.EndDate.AddDate(0, -dataRefreshNum*3, 0).Format(utils.FormatDate)
+				} else if v.Frequency == "半年度" {
+					startDate = v.EndDate.AddDate(0, -dataRefreshNum*6, 0).Format(utils.FormatDate)
+				} else if v.Frequency == "年度" {
+					startDate = v.EndDate.AddDate(-dataRefreshNum, 0, 0).Format(utils.FormatDate)
+				} else {
+					startDate = v.EndDate.AddDate(0, 0, -utils.DATA_REFRESH).Format(utils.FormatDate)
+				}
+			}
+			fmt.Println(startDate)
+
+			// 数据更新
+			resp, tmpErr := data.RefreshEdbData(v.EdbInfoId, v.Source, v.SubSource, v.EdbCode, startDate)
+			if tmpErr != nil {
+				errMsgList = append(errMsgList, v.EdbCode+"RefreshEdbData Err:"+tmpErr.Error())
+				continue
+			}
+			if resp.Ret != 200 {
+				errMsgList = append(errMsgList, v.EdbCode+";RefreshEdbData Err:"+resp.Msg+";ErrMsg:"+resp.ErrMsg)
+				continue
+			}
 		}
 	}
 
@@ -526,3 +584,198 @@ func getPreviousHalfHour(now time.Time) string {
 	}
 	return fmt.Sprintf("%02d:%02d", now.Hour(), 0)
 }
+
+// 根据配置把钢联化工和wind指标设置成禁止刷新
+func DisableEdbRefresh(cont context.Context) (err error) {
+	//设置刷新key,如果没有执行完 报错提示
+	cacheKey := "eta_task:DisableEdbRefresh"
+	deleteCache := true
+	defer func() {
+		if deleteCache {
+			utils.Rc.Delete(cacheKey)
+		}
+		if err != nil {
+			tips := "DisableEdbRefresh-钢联化工和wind指标设置成禁止刷新失败, ErrMsg:\n" + err.Error()
+			utils.FileLog.Info(tips)
+			go alarm_msg.SendAlarmMsg(tips, 3)
+		}
+	}()
+	if !utils.Rc.SetNX(cacheKey, 1, 2*time.Minute) {
+		deleteCache = false
+		err = fmt.Errorf("系统处理中,请稍后重试!")
+		return
+	}
+	//查询配置,如果未开启自动设置禁止刷新,则无需处理
+	obj := new(models.BusinessConf)
+	conf, err := obj.GetItemByConfKey("EdbStopRefreshRule")
+	if err != nil {
+		if err.Error() == utils.ErrNoRow() {
+			err = fmt.Errorf("未找到配置项,无需处理")
+			return
+		}
+		return
+	}
+	//将json转为结构体
+	rule := new(models.EdbStopRefreshRule)
+	err = json.Unmarshal([]byte(conf.ConfVal), rule)
+	if err != nil {
+		return
+	}
+	//判断是否开启自动设置禁止刷新
+	if rule.IsOpen == 0 {
+		return
+	}
+
+	//获取当前时间
+	now := time.Now()
+	if rule.BaseIndexStopDays > 0 { //设置数据源钢联化工指标禁止更新
+		baseIndexEndDate := now.AddDate(0, 0, -rule.BaseIndexStopDays+1).Format(utils.FormatDate)
+
+		// 查询钢联化工指标,查询创建时间在baseIndexStartDate前,的所有钢联化工指标,分批查询,先查总数,再查列表
+		totalCount, e := data_manage.GetCountRefreshBaseFromMysteelChemicalIndexItemByCreateTime(baseIndexEndDate)
+		if e != nil {
+			err = fmt.Errorf("查询钢联化工指标总数失败:%v", e)
+			return
+		}
+
+		//分页查询
+		pageSize := 100
+		pageNum := (int(totalCount) + 99) / pageSize // 使用整数除法,并添加一页以防有余数
+		stopRefreshIds := make([]int32, 0)
+		for i := 0; i < pageNum; i++ {
+			start := i * pageSize
+			indexItems, e := data_manage.GetRefreshBaseFromMysteelChemicalIndexItemByCreateTime(baseIndexEndDate, start, pageSize)
+			if e != nil {
+				err = fmt.Errorf("分页查询钢联化工指标失败:%v", e)
+				return
+			}
+			if len(indexItems) == 0 {
+				continue
+			}
+			indexCodeList := make([]string, 0)
+			for _, indexItem := range indexItems {
+				indexCodeList = append(indexCodeList, indexItem.IndexCode)
+			}
+			condition := ` AND source=? AND edb_code in (` + utils.GetOrmInReplace(len(indexCodeList)) + `)`
+			var pars []interface{}
+			pars = append(pars, utils.DATA_SOURCE_MYSTEEL_CHEMICAL, indexCodeList)
+
+			// 查询指标库里这些指标是否已创建
+			edbList, e := data_manage.GetEdbInfoByCondition(condition, pars, 0)
+			if e != nil {
+				err = fmt.Errorf("查询指标库里这些指标是否被创建失败:%v", e)
+				return
+			}
+			edbMap := make(map[string]bool)
+			for _, edb := range edbList {
+				edbMap[edb.EdbCode] = true
+			}
+			for _, indexItem := range indexItems {
+				// 判断指标是否被创建
+				if _, ok := edbMap[indexItem.IndexCode]; !ok {
+					stopRefreshIds = append(stopRefreshIds, indexItem.BaseFromMysteelChemicalIndexId)
+					if len(stopRefreshIds) > 100 {
+						err = data_manage.SetStopRefreshMysteelChemicalIndex(stopRefreshIds)
+						if err != nil {
+							err = fmt.Errorf("设置禁止刷新失败:%v", err)
+							return
+						}
+						stopRefreshIds = make([]int32, 0)
+					}
+				}
+			}
+		}
+		// 未被创建,则设置禁止刷新
+		if len(stopRefreshIds) > 0 {
+			err = data_manage.SetStopRefreshMysteelChemicalIndex(stopRefreshIds)
+			if err != nil {
+				err = fmt.Errorf("设置禁止刷新失败:%v", err)
+				return
+			}
+		}
+	}
+
+	if rule.EdbStopDays > 0 {
+		// 查询钢联和wind来源的指标
+		edbEndDate := now.AddDate(0, 0, -rule.EdbStopDays+1).Format(utils.FormatDate)
+
+		condition := ` AND no_update=0 AND source in (?,?) AND create_time < ?`
+		var pars []interface{}
+		pars = append(pars, utils.DATA_SOURCE_MYSTEEL_CHEMICAL, utils.DATA_SOURCE_WIND, edbEndDate)
+		// 查询钢联化工指标和wind指标 分批查询,先查总数,再查列表
+		totalCount, e := data_manage.GetEdbInfoCountByCondition(condition, pars)
+		if e != nil {
+			err = fmt.Errorf("查询钢联化工指标总数失败:%v", e)
+			return
+		}
+
+		//分页查询
+		pageSize := 100
+		pageNum := (int(totalCount) + 99) / pageSize // 使用整数除法,并添加一页以防有余数
+		stopRefreshIds := make([]int, 0)
+		stopRefreshMysteelCode := make([]string, 0)
+		for i := 0; i < pageNum; i++ {
+			start := i * pageSize
+			edbItems, e := data_manage.GetEdbInfoPageByCondition(condition, pars, start, pageSize)
+			if e != nil {
+				err = fmt.Errorf("分页查询钢联化工指标失败:%v", e)
+				return
+			}
+			if len(edbItems) == 0 {
+				continue
+			}
+			edbInfoIds := make([]int, 0)
+			for _, item := range edbItems {
+				edbInfoIds = append(edbInfoIds, item.EdbInfoId)
+			}
+			// 查询指标库里这些指标 引用情况
+			relationList, e := data_manage.GetEdbInfoRelationByEdbInfoIds(edbInfoIds)
+			if e != nil {
+				err = fmt.Errorf("查询指标库里这些指标是否被创建失败:%v", e)
+				return
+			}
+			edbMap := make(map[int]struct{})
+			for _, item := range relationList {
+				edbMap[item] = struct{}{}
+			}
+			for _, item := range edbItems {
+				if _, ok := edbMap[item.EdbInfoId]; !ok {
+					stopRefreshIds = append(stopRefreshIds, item.EdbInfoId)
+					if item.Source == utils.DATA_SOURCE_MYSTEEL_CHEMICAL {
+						stopRefreshMysteelCode = append(stopRefreshMysteelCode, item.EdbCode)
+					}
+					// 更新指标禁止刷新状态
+					if len(stopRefreshIds) > 100 {
+						calculateEdbIds, tmpErr := data_manage.GetAllCalculateEdbIdsByEdbInfoIds(stopRefreshIds)
+						if tmpErr != nil {
+							err = fmt.Errorf("查询计算指标信息失败:%v", tmpErr)
+							return
+						}
+						err = data_manage.ModifyEdbUpdateStatus(stopRefreshIds, stopRefreshMysteelCode, calculateEdbIds)
+						if err != nil {
+							err = fmt.Errorf("更新指标禁止刷新状态失败:%v", err)
+							return
+						}
+						stopRefreshIds = []int{}
+						stopRefreshMysteelCode = []string{}
+					}
+				}
+			}
+		}
+
+		// 更新指标禁止刷新状态
+		if len(stopRefreshIds) > 0 {
+			calculateEdbIds, tmpErr := data_manage.GetAllCalculateEdbIdsByEdbInfoIds(stopRefreshIds)
+			if tmpErr != nil {
+				err = fmt.Errorf("查询计算指标信息失败:%v", tmpErr)
+				return
+			}
+			err = data_manage.ModifyEdbUpdateStatus(stopRefreshIds, stopRefreshMysteelCode, calculateEdbIds)
+			if err != nil {
+				err = fmt.Errorf("更新指标禁止刷新状态失败:%v", err)
+				return
+			}
+		}
+	}
+	return
+}

+ 1124 - 0
services/edb_relation.go

@@ -0,0 +1,1124 @@
+package services
+
+import (
+	"encoding/json"
+	"eta/eta_task/models/data_manage"
+	"eta/eta_task/models/data_manage/cross_variety"
+	"eta/eta_task/models/data_manage/excel"
+	"eta/eta_task/models/fe_calendar"
+	"eta/eta_task/models/sandbox"
+	"eta/eta_task/services/alarm_msg"
+	"eta/eta_task/utils"
+	"fmt"
+	"time"
+)
+
+func InitEdbRelation() {
+	InitChartEdbRelation()
+	InitChartCrossVariety()
+	initCalendarIndicatorRelation()
+	initSandBoxEdbRelation()
+	InitExcelEdbRelation()
+}
+func InitChartEdbRelation() {
+	fmt.Println("开始处理图表中的指标引用")
+	var err error
+	var addNum int
+	defer func() {
+		if err != nil {
+			msg := fmt.Sprintf("初始化指标在图表中的引用失败 InitChartEdbRelation  err: %v", err)
+			utils.FileLog.Info(msg)
+			fmt.Println(msg)
+			go alarm_msg.SendAlarmMsg(msg, 3)
+		}
+	}()
+	//查询chart_edb_mapping 表
+	total, err := data_manage.GetChartEdbMappingTotal()
+	if err != nil {
+		err = fmt.Errorf("查询图表关联指标失败 err: %v", err)
+		return
+	}
+	if total == 0 {
+		return
+	}
+	//分页查询,每次处理500条记录
+	pageSize := 500
+	totalPage := (total + pageSize - 1) / pageSize // 使用整数除法,并添加一页以防有余数
+	addList := make([]*data_manage.EdbInfoRelation, 0)
+	//查询图表列表
+	for i := 0; i < totalPage; i += 1 {
+		startSize := i * pageSize
+		list, e := data_manage.GetChartEdbMappingList(startSize, pageSize)
+		if e != nil {
+			err = fmt.Errorf("查询图表关联指标列表失败 Err:%s", e)
+			return
+		}
+		if len(list) == 0 {
+			break
+		}
+
+		edbInfoIds := make([]int, 0)
+		for _, v := range list {
+			edbInfoIds = append(edbInfoIds, v.EdbInfoId)
+		}
+		// 查询指标信息表
+		edbInfoList, e := data_manage.GetEdbInfoByIdList(edbInfoIds)
+		if e != nil {
+			err = fmt.Errorf("查询指标信息列表失败 Err:%s", e)
+			return
+		}
+		if len(edbInfoList) == 0 {
+			continue
+		}
+		// 查询计算指标信息,并且建立关联关系
+		// 查询间接引用的指标信息
+		calculateEdbMappingListMap, calculateEdbMappingIdsMap, e := GetEdbListByEdbInfoId(edbInfoList)
+		if e != nil {
+			err = fmt.Errorf("查询计算指标信息失败,%s", e.Error())
+			return
+		}
+		// 查询指标间接引用
+		edbInfoMap := make(map[int]*data_manage.EdbInfo)
+		for _, v := range edbInfoList {
+			edbInfoMap[v.EdbInfoId] = v
+		}
+
+		// 筛选有用的图表
+		finalList := make([]*data_manage.ChartEdbMapping, 0)
+		chartIds := make([]int, 0)
+		for _, v := range list {
+			if _, ok2 := edbInfoMap[v.EdbInfoId]; !ok2 {
+				continue
+			}
+			finalList = append(finalList, v)
+			chartIds = append(chartIds, v.ChartInfoId)
+		}
+		if len(chartIds) == 0 {
+			continue
+		}
+		// 查询图表信息
+		chartInfoList, e := data_manage.GetChartInfoByChartInfoIds(chartIds)
+		if e != nil {
+			err = fmt.Errorf("查询图表信息列表失败 Err:%s", e)
+			return
+		}
+		chartInfoMap := make(map[int]*data_manage.ChartInfo)
+		for _, v := range chartInfoList {
+			chartInfoMap[v.ChartInfoId] = v
+		}
+
+		//查询引用关系列表,
+		chartEdbRelationList, e := data_manage.GetEdbInfoRelationByReferObjectIds(chartIds, utils.EDB_RELATION_CHART)
+		if e != nil {
+			err = fmt.Errorf("查询图表引用关系列表失败 Err:%s", e)
+			return
+		}
+		existRelationMap := make(map[string]struct{})
+		for _, v := range chartEdbRelationList {
+			name := fmt.Sprintf("%d-%d", v.ReferObjectId, v.EdbInfoId)
+			existRelationMap[name] = struct{}{}
+		}
+		for _, v := range finalList {
+			nowTime := time.Now()
+			name := fmt.Sprintf("%d-%d", v.ChartInfoId, v.EdbInfoId)
+			if _, ok := existRelationMap[name]; !ok {
+				//查询图表信息
+				chartInfo, ok1 := chartInfoMap[v.ChartInfoId]
+				if !ok1 {
+					continue
+				}
+				edbInfo, ok2 := edbInfoMap[v.EdbInfoId]
+				if !ok2 {
+					continue
+				}
+				//todo 引用时间
+				tmp := &data_manage.EdbInfoRelation{
+					ReferObjectId:      v.ChartInfoId,
+					ReferObjectType:    utils.EDB_RELATION_CHART,
+					ReferObjectSubType: chartInfo.Source,
+					EdbInfoId:          v.EdbInfoId,
+					EdbName:            edbInfo.EdbName,
+					Source:             edbInfo.Source,
+					EdbCode:            edbInfo.EdbCode,
+					CreateTime:         nowTime,
+					ModifyTime:         nowTime,
+					RelationTime:       v.CreateTime,
+				}
+				tmp.RelationCode = fmt.Sprintf("%d_%d_%d_%d", tmp.EdbInfoId, tmp.ReferObjectId, tmp.ReferObjectType, tmp.ReferObjectSubType)
+				addList = append(addList, tmp)
+				existRelationMap[name] = struct{}{}
+				// 添加间接引用记录
+				if edbInfo.EdbType == 2 || edbInfo.EdbInfoType == 1 {
+					childEdbMappingIds, ok1 := calculateEdbMappingIdsMap[edbInfo.EdbInfoId]
+					if !ok1 {
+						continue
+					}
+					for _, childEdbMappingId := range childEdbMappingIds {
+						childEdbMapping, ok2 := calculateEdbMappingListMap[childEdbMappingId]
+						if !ok2 {
+							continue
+						}
+						name1 := fmt.Sprintf("%d-%d", v.ChartInfoId, childEdbMapping.FromEdbInfoId)
+						if _, ok2 := existRelationMap[name1]; !ok2 { //如果已经被直接引用了,则无需添加到间接引用记录中
+							continue
+						}
+						tmp1 := &data_manage.EdbInfoRelation{
+							ReferObjectId:      v.ChartInfoId,
+							ReferObjectType:    utils.EDB_RELATION_CHART,
+							ReferObjectSubType: chartInfo.Source,
+							EdbInfoId:          childEdbMapping.FromEdbInfoId,
+							EdbName:            childEdbMapping.FromEdbName,
+							Source:             childEdbMapping.FromSource,
+							EdbCode:            childEdbMapping.FromEdbCode,
+							CreateTime:         nowTime,
+							ModifyTime:         nowTime,
+							RelationTime:       v.CreateTime,
+							RelationType:       1,
+							RootEdbInfoId:      edbInfo.EdbInfoId,
+							ChildEdbInfoId:     childEdbMapping.EdbInfoId,
+							RelationCode:       tmp.RelationCode,
+						}
+						addList = append(addList, tmp1)
+						// todo 防止重复
+					}
+				}
+
+				if len(addList) > pageSize {
+					err = data_manage.AddEdbInfoRelationMulti(addList)
+					if err != nil {
+						err = fmt.Errorf("新增引用记录失败 Err:%s", err)
+						return
+					}
+					addNum += len(addList)
+					addList = make([]*data_manage.EdbInfoRelation, 0)
+				}
+			}
+		}
+	}
+	//拿到500个数据ID,判断相关的引用记录,如果已存在则直接过滤,不存在则新增
+	if len(addList) > 0 {
+		err = data_manage.AddEdbInfoRelationMulti(addList)
+		if err != nil {
+			err = fmt.Errorf("新增引用记录失败 Err:%s", err)
+			return
+		}
+		addNum += len(addList)
+	}
+	fmt.Printf("图表指标引用记录处理完成, 新增%d条记录\n", addNum)
+	return
+}
+
+// InitChartCrossVariety 处理特殊图表,跨品种分析图表
+func InitChartCrossVariety() {
+	fmt.Println("开始跨品种分析图表中的指标引用")
+	var addNum int
+	var err error
+	defer func() {
+		if err != nil {
+			msg := fmt.Sprintf("初始化指标在跨品种分析图表中的引用失败 InitChartCrossVariety  err: %v", err)
+			utils.FileLog.Info(msg)
+			fmt.Println(msg)
+			go alarm_msg.SendAlarmMsg(msg, 3)
+		}
+	}()
+	total, err := cross_variety.GetChartInfoCrossVarietyTotal()
+	if err != nil {
+		err = fmt.Errorf("查询图表关联指标失败 err: %v", err)
+		return
+	}
+	if total == 0 {
+		return
+	}
+	//分页查询,每次处理500条记录
+	pageSize := 500
+	totalPage := (total + pageSize - 1) / pageSize // 使用整数除法,并添加一页以防有余数
+	addList := make([]*data_manage.EdbInfoRelation, 0)
+	//查询图表列表
+	for i := 0; i < totalPage; i += 1 {
+		startSize := i * pageSize
+		list, e := cross_variety.GetChartInfoCrossVarietyList(startSize, pageSize)
+		if e != nil {
+			err = fmt.Errorf("查询图表关联指标列表失败 Err:%s", e)
+			return
+		}
+		if len(list) == 0 {
+			break
+		}
+		chartIds := make([]int, 0)
+		tagIds := make([]int, 0)
+		tagIdsMap := make(map[int]struct{})
+		tagChartMap := make(map[int][]*cross_variety.ChartInfoCrossVariety)
+		for _, v := range list {
+			if _, ok := tagIdsMap[v.ChartXTagId]; !ok {
+				tagIds = append(tagIds, v.ChartXTagId)
+				tagIdsMap[v.ChartXTagId] = struct{}{}
+			}
+			if _, ok := tagIdsMap[v.ChartYTagId]; !ok {
+				tagIds = append(tagIds, v.ChartYTagId)
+				tagIdsMap[v.ChartYTagId] = struct{}{}
+			}
+			if chartCross, ok := tagChartMap[v.ChartXTagId]; ok {
+				chartCross = append(chartCross, v)
+				tagChartMap[v.ChartXTagId] = chartCross
+			} else {
+				chartCross = make([]*cross_variety.ChartInfoCrossVariety, 0)
+				chartCross = append(chartCross, v)
+				tagChartMap[v.ChartXTagId] = chartCross
+			}
+			if chartCross, ok := tagChartMap[v.ChartYTagId]; ok {
+				chartCross = append(chartCross, v)
+				tagChartMap[v.ChartYTagId] = chartCross
+			} else {
+				chartCross = make([]*cross_variety.ChartInfoCrossVariety, 0)
+				chartCross = append(chartCross, v)
+				tagChartMap[v.ChartYTagId] = chartCross
+			}
+		}
+		chartTagVarietyList, e := cross_variety.GetChartTagVarietyEdbInfoIdsByTagIds(tagIds)
+		if e != nil {
+			err = fmt.Errorf("查询指标信息列表失败 Err:%s", e)
+			return
+		}
+		edbInfoIds := make([]int, 0)
+		chartTagVarietyMap := make(map[int][]*cross_variety.ChartTagVariety)
+		for _, v := range chartTagVarietyList {
+			if tagList, ok := chartTagVarietyMap[v.EdbInfoId]; ok {
+				tagList = append(tagList, v)
+				chartTagVarietyMap[v.EdbInfoId] = tagList
+			} else {
+				tagList = make([]*cross_variety.ChartTagVariety, 0)
+				tagList = append(tagList, v)
+				chartTagVarietyMap[v.EdbInfoId] = tagList
+			}
+
+			edbInfoIds = append(edbInfoIds, v.EdbInfoId)
+		}
+
+		// 查询指标信息表
+		edbInfoList, e := data_manage.GetEdbInfoByIdList(edbInfoIds)
+		if e != nil {
+			err = fmt.Errorf("查询指标信息列表失败 Err:%s", e)
+			return
+		}
+		if len(edbInfoList) == 0 {
+			continue
+		}
+		// 查询计算指标信息,并且建立关联关系
+		// 查询间接引用的指标信息
+		calculateEdbMappingListMap, calculateEdbMappingIdsMap, e := GetEdbListByEdbInfoId(edbInfoList)
+		if e != nil {
+			err = fmt.Errorf("查询计算指标信息失败,%s", e.Error())
+			return
+		}
+		edbInfoMap := make(map[int]*data_manage.EdbInfo)
+		chartInfoCrossMap := make(map[int]struct{})
+		chartInfoCrossList := make([]*cross_variety.ChartInfoCrossVariety, 0)
+		edbCrossMap := make(map[int][]*cross_variety.ChartInfoCrossVariety)
+		for _, v := range edbInfoList {
+			edbInfoMap[v.EdbInfoId] = v
+			if tagList, ok := chartTagVarietyMap[v.EdbInfoId]; ok {
+				for _, tag := range tagList {
+					if chartCross, ok2 := tagChartMap[tag.ChartTagId]; ok2 {
+						for _, crossItem := range chartCross {
+							if _, ok3 := chartInfoCrossMap[crossItem.ChartInfoId]; !ok3 {
+								chartInfoCrossMap[crossItem.ChartInfoId] = struct{}{}
+								chartInfoCrossList = append(chartInfoCrossList, crossItem)
+								chartIds = append(chartIds, crossItem.ChartInfoId)
+							}
+						}
+					}
+				}
+			}
+			edbCrossMap[v.EdbInfoId] = chartInfoCrossList
+			chartInfoCrossMap = make(map[int]struct{})
+			chartInfoCrossList = make([]*cross_variety.ChartInfoCrossVariety, 0)
+		}
+
+		/*// 查询图表信息
+		chartInfoList, e := data_manage.GetChartInfoByChartInfoIds(chartIds)
+		if e != nil {
+			err = fmt.Errorf("查询图表信息列表失败 Err:%s", e)
+			return
+		}
+		chartInfoMap := make(map[int]*data_manage.ChartInfo)
+		for _, v := range chartInfoList {
+			chartInfoMap[v.ChartInfoId] = v
+		}
+		*/
+		//查询引用关系列表,
+		chartEdbRelationList, e := data_manage.GetEdbInfoRelationByReferObjectIds(chartIds, utils.EDB_RELATION_CHART)
+		if e != nil {
+			err = fmt.Errorf("查询图表引用关系列表失败 Err:%s", e)
+			return
+		}
+		existRelationMap := make(map[string]struct{})
+		for _, v := range chartEdbRelationList {
+			name := fmt.Sprintf("%d-%d", v.ReferObjectId, v.EdbInfoId)
+			existRelationMap[name] = struct{}{}
+		}
+		for edbInfoId, chartCrossList := range edbCrossMap {
+			nowTime := time.Now()
+			for _, item := range chartCrossList {
+				name := fmt.Sprintf("%d-%d", item.ChartInfoId, edbInfoId)
+				if _, ok1 := existRelationMap[name]; !ok1 {
+					edbInfo, ok2 := edbInfoMap[edbInfoId]
+					if !ok2 {
+						continue
+					}
+					//todo 引用时间
+					tmp := &data_manage.EdbInfoRelation{
+						ReferObjectId:      item.ChartInfoId,
+						ReferObjectType:    utils.EDB_RELATION_CHART,
+						ReferObjectSubType: utils.CHART_SOURCE_CROSS_HEDGING,
+						EdbInfoId:          edbInfoId,
+						EdbName:            edbInfo.EdbName,
+						Source:             edbInfo.Source,
+						EdbCode:            edbInfo.EdbCode,
+						CreateTime:         nowTime,
+						ModifyTime:         nowTime,
+						RelationTime:       item.CreateTime,
+					}
+					tmp.RelationCode = fmt.Sprintf("%d_%d_%d_%d", tmp.EdbInfoId, tmp.ReferObjectId, tmp.ReferObjectType, tmp.ReferObjectSubType)
+					addList = append(addList, tmp)
+					existRelationMap[name] = struct{}{}
+					// 添加间接引用记录
+					if edbInfo.EdbType == 2 || edbInfo.EdbInfoType == 1 {
+						childEdbMappingIds, ok1 := calculateEdbMappingIdsMap[edbInfo.EdbInfoId]
+						if !ok1 {
+							continue
+						}
+						for _, childEdbMappingId := range childEdbMappingIds {
+							childEdbMapping, ok2 := calculateEdbMappingListMap[childEdbMappingId]
+							if !ok2 {
+								continue
+							}
+							name1 := fmt.Sprintf("%d-%d", item.ChartInfoId, childEdbMapping.FromEdbInfoId)
+							if _, ok2 := existRelationMap[name1]; !ok2 { //如果已经被直接引用了,则无需添加到间接引用记录中
+								continue
+							}
+
+							tmp1 := &data_manage.EdbInfoRelation{
+								ReferObjectId:      item.ChartInfoId,
+								ReferObjectType:    utils.EDB_RELATION_CHART,
+								ReferObjectSubType: utils.CHART_SOURCE_CROSS_HEDGING,
+								EdbInfoId:          childEdbMapping.FromEdbInfoId,
+								EdbName:            childEdbMapping.FromEdbName,
+								Source:             childEdbMapping.FromSource,
+								EdbCode:            childEdbMapping.FromEdbCode,
+								CreateTime:         nowTime,
+								ModifyTime:         nowTime,
+								RelationTime:       item.CreateTime,
+								RelationType:       1,
+								RootEdbInfoId:      edbInfo.EdbInfoId,
+								ChildEdbInfoId:     childEdbMapping.EdbInfoId,
+								RelationCode:       tmp.RelationCode,
+							}
+							addList = append(addList, tmp1)
+							// todo 防止重复
+						}
+					}
+					if len(addList) > pageSize {
+						err = data_manage.AddEdbInfoRelationMulti(addList)
+						if err != nil {
+							err = fmt.Errorf("新增引用记录失败 Err:%s", err)
+							return
+						}
+						addNum += len(addList)
+						addList = make([]*data_manage.EdbInfoRelation, 0)
+					}
+				}
+			}
+		}
+	}
+	//拿到500个数据ID,判断相关的引用记录,如果已存在则直接过滤,不存在则新增
+	if len(addList) > 0 {
+		err = data_manage.AddEdbInfoRelationMulti(addList)
+		if err != nil {
+			err = fmt.Errorf("新增引用记录失败 Err:%s", err)
+			return
+		}
+		addNum += len(addList)
+	}
+	fmt.Printf("跨品种分析图表指标引用记录处理完成, 新增%d条记录\n", addNum)
+	return
+}
+
+// 初始化事件日历中的指标引用
+func initCalendarIndicatorRelation() {
+	fmt.Println("开始处理事件日历中的指标引用")
+	var addNum int
+	var err error
+	defer func() {
+		if err != nil {
+			msg := fmt.Sprintf("初始化指标在事件日历中的引用失败 initCalendarIndicatorRelation  err: %v", err)
+			utils.FileLog.Info(msg)
+			fmt.Println(msg)
+			go alarm_msg.SendAlarmMsg(msg, 3)
+		}
+	}()
+	//查询chart_edb_mapping 表
+	obj := new(fe_calendar.FeCalendarMatter)
+	condition := " AND edb_info_id > 0"
+	total, err := obj.GetCountByCondition(condition, []interface{}{})
+	if err != nil {
+		err = fmt.Errorf("查询事件日历关联指标失败 err: %v", err)
+		return
+	}
+	if total == 0 {
+		return
+	}
+	//分页查询,每次处理500条记录
+	pageSize := 500
+	totalPage := (total + pageSize - 1) / pageSize // 使用整数除法,并添加一页以防有余数
+	addList := make([]*data_manage.EdbInfoRelation, 0)
+	//查询图表列表
+	for i := 0; i < totalPage; i += 1 {
+		startSize := i * pageSize
+		list, e := obj.GetPageItemsByCondition(condition, []interface{}{}, []string{}, "", startSize, pageSize)
+		if e != nil {
+			err = fmt.Errorf("查询事件日历关联指标列表失败 Err:%s", e)
+			return
+		}
+		if len(list) == 0 {
+			break
+		}
+
+		edbInfoIds := make([]int, 0)
+		edbInfoMatterMap := make(map[int][]*fe_calendar.FeCalendarMatter)
+		for _, v := range list {
+			edbInfoIds = append(edbInfoIds, v.EdbInfoId)
+			items, ok := edbInfoMatterMap[v.EdbInfoId]
+			if ok {
+				items = append(items, v)
+				edbInfoMatterMap[v.EdbInfoId] = items
+			} else {
+				items = make([]*fe_calendar.FeCalendarMatter, 0)
+				items = append(items, v)
+				edbInfoMatterMap[v.EdbInfoId] = items
+			}
+		}
+		// 查询指标信息表
+		edbInfoList, e := data_manage.GetEdbInfoByIdList(edbInfoIds)
+		if e != nil {
+			err = fmt.Errorf("查询指标信息列表失败 Err:%s", e)
+			return
+		}
+		if len(edbInfoList) == 0 {
+			continue
+		}
+
+		// 查询计算指标信息,并且建立关联关系
+		// 查询间接引用的指标信息
+		calculateEdbMappingListMap, calculateEdbMappingIdsMap, e := GetEdbListByEdbInfoId(edbInfoList)
+		if e != nil {
+			err = fmt.Errorf("查询计算指标信息失败,%s", e.Error())
+			return
+		}
+		edbInfoMap := make(map[int]*data_manage.EdbInfo)
+		matterIds := make([]int, 0)
+		for _, v := range edbInfoList {
+			edbInfoMap[v.EdbInfoId] = v
+			items, ok := edbInfoMatterMap[v.EdbInfoId]
+			if ok {
+				for _, item := range items {
+					matterIds = append(matterIds, item.FeCalendarMatterId)
+				}
+			}
+		}
+
+		//查询引用关系列表,
+		chartEdbRelationList, e := data_manage.GetEdbInfoRelationByReferObjectIds(matterIds, utils.EDB_RELATION_CALENDAR)
+		if e != nil {
+			err = fmt.Errorf("查询图表引用关系列表失败 Err:%s", e)
+			return
+		}
+		existRelationMap := make(map[string]struct{})
+		for _, v := range chartEdbRelationList {
+			name := fmt.Sprintf("%d-%d", v.ReferObjectId, v.EdbInfoId)
+			existRelationMap[name] = struct{}{}
+		}
+		for edbInfoId, edbInfo := range edbInfoMap {
+			nowTime := time.Now()
+			items, ok := edbInfoMatterMap[edbInfoId]
+			if ok {
+				for _, v := range items {
+					name := fmt.Sprintf("%d-%d", v.FeCalendarMatterId, v.EdbInfoId)
+					if _, ok1 := existRelationMap[name]; !ok1 {
+						//todo 引用时间
+						tmp := &data_manage.EdbInfoRelation{
+							ReferObjectId:   v.FeCalendarMatterId,
+							ReferObjectType: utils.EDB_RELATION_CALENDAR,
+							EdbInfoId:       v.EdbInfoId,
+							EdbName:         edbInfo.EdbName,
+							Source:          edbInfo.Source,
+							EdbCode:         edbInfo.EdbCode,
+							CreateTime:      nowTime,
+							ModifyTime:      nowTime,
+							RelationTime:    v.CreateTime,
+						}
+						tmp.RelationCode = fmt.Sprintf("%d_%d_%d_%d", tmp.EdbInfoId, tmp.ReferObjectId, tmp.ReferObjectType, tmp.ReferObjectSubType)
+						addList = append(addList, tmp)
+						existRelationMap[name] = struct{}{}
+						// 添加间接引用记录
+						if edbInfo.EdbType == 2 || edbInfo.EdbInfoType == 1 {
+							childEdbMappingIds, ok1 := calculateEdbMappingIdsMap[edbInfo.EdbInfoId]
+							if !ok1 {
+								continue
+							}
+							for _, childEdbMappingId := range childEdbMappingIds {
+								childEdbMapping, ok2 := calculateEdbMappingListMap[childEdbMappingId]
+								if !ok2 {
+									continue
+								}
+								name1 := fmt.Sprintf("%d-%d", v.FeCalendarMatterId, childEdbMapping.FromEdbInfoId)
+								if _, ok2 := existRelationMap[name1]; !ok2 { //如果已经被直接引用了,则无需添加到间接引用记录中
+									continue
+								}
+								tmp1 := &data_manage.EdbInfoRelation{
+									ReferObjectId:   v.FeCalendarMatterId,
+									ReferObjectType: utils.EDB_RELATION_CALENDAR,
+									EdbInfoId:       childEdbMapping.FromEdbInfoId,
+									EdbName:         childEdbMapping.FromEdbName,
+									Source:          childEdbMapping.FromSource,
+									EdbCode:         childEdbMapping.FromEdbCode,
+									CreateTime:      nowTime,
+									ModifyTime:      nowTime,
+									RelationTime:    v.CreateTime,
+									RelationType:    1,
+									RootEdbInfoId:   edbInfo.EdbInfoId,
+									ChildEdbInfoId:  childEdbMapping.EdbInfoId,
+									RelationCode:    tmp.RelationCode,
+								}
+								addList = append(addList, tmp1)
+								// todo 防止重复
+							}
+						}
+						if len(addList) > pageSize {
+							err = data_manage.AddEdbInfoRelationMulti(addList)
+							if err != nil {
+								err = fmt.Errorf("新增引用记录失败 Err:%s", err)
+								return
+							}
+							addNum += len(addList)
+							addList = make([]*data_manage.EdbInfoRelation, 0)
+						}
+					}
+				}
+			}
+
+		}
+	}
+	//拿到500个数据ID,判断相关的引用记录,如果已存在则直接过滤,不存在则新增
+	if len(addList) > 0 {
+		err = data_manage.AddEdbInfoRelationMulti(addList)
+		if err != nil {
+			err = fmt.Errorf("新增引用记录失败 Err:%s", err)
+			return
+		}
+		addNum += len(addList)
+	}
+	fmt.Printf("事件日历指标引用记录处理完成, 新增%d条记录\n", addNum)
+	return
+}
+
+// 初始化表格中的指标引用
+func InitExcelEdbRelation() {
+	fmt.Println("开始处理表格中的指标引用")
+	var err error
+	var addNum int
+	defer func() {
+		if err != nil {
+			msg := fmt.Sprintf("初始化指标在表格中的引用失败 InitChartEdbRelation  err: %v", err)
+			utils.FileLog.Info(msg)
+			fmt.Println(msg)
+			go alarm_msg.SendAlarmMsg(msg, 3)
+		}
+	}()
+	//查询表格指标绑定表
+	sources := []int{utils.TIME_TABLE, utils.MIXED_TABLE, utils.BALANCE_TABLE}
+	total, err := excel.GetExcelEdbMappingTotalBySource(sources)
+	if err != nil {
+		err = fmt.Errorf("查询表格关联指标失败 err: %v", err)
+		return
+	}
+	if total == 0 {
+		return
+	}
+	//分页查询,每次处理100条记录
+	pageSize := 100
+	totalPage := (total + pageSize - 1) / pageSize // 使用整数除法,并添加一页以防有余数
+	addList := make([]*data_manage.EdbInfoRelation, 0)
+	//查询表格列表
+	for i := 0; i < totalPage; i += 1 {
+		startSize := i * pageSize
+		list, e := excel.GetExcelEdbMappingListBySource(sources, startSize, pageSize)
+		if e != nil {
+			err = fmt.Errorf("查询表格关联指标列表失败 Err:%s", e)
+			return
+		}
+		if len(list) == 0 {
+			break
+		}
+
+		edbInfoIds := make([]int, 0)
+		for _, v := range list {
+			edbInfoIds = append(edbInfoIds, v.EdbInfoId)
+		}
+		// 查询指标信息表
+		edbInfoList, e := data_manage.GetEdbInfoByIdList(edbInfoIds)
+		if e != nil {
+			err = fmt.Errorf("查询指标信息列表失败 Err:%s", e)
+			return
+		}
+		if len(edbInfoList) == 0 {
+			continue
+		}
+		// 查询计算指标信息,并且建立关联关系
+		// 查询间接引用的指标信息
+		calculateEdbMappingListMap, calculateEdbMappingIdsMap, e := GetEdbListByEdbInfoId(edbInfoList)
+		if e != nil {
+			err = fmt.Errorf("查询计算指标信息失败,%s", e.Error())
+			return
+		}
+		// 查询指标间接引用
+		edbInfoMap := make(map[int]*data_manage.EdbInfo)
+		for _, v := range edbInfoList {
+			edbInfoMap[v.EdbInfoId] = v
+		}
+
+		// 筛选有用的表格
+		excelIds := make([]int, 0)
+		for _, v := range list {
+			excelIds = append(excelIds, v.ExcelInfoId)
+		}
+
+		//查询引用关系列表,
+		chartEdbRelationList, e := data_manage.GetEdbInfoRelationByReferObjectIds(excelIds, utils.EDB_RELATION_TABLE)
+		if e != nil {
+			err = fmt.Errorf("查询表格引用关系列表失败 Err:%s", e)
+			return
+		}
+		existRelationMap := make(map[string]struct{})
+		for _, v := range chartEdbRelationList {
+			name := fmt.Sprintf("%d-%d", v.ReferObjectId, v.EdbInfoId)
+			existRelationMap[name] = struct{}{}
+		}
+		for _, v := range list {
+			nowTime := time.Now()
+			name := fmt.Sprintf("%d-%d", v.ExcelInfoId, v.EdbInfoId)
+			if _, ok := existRelationMap[name]; !ok {
+				edbInfo, ok2 := edbInfoMap[v.EdbInfoId]
+				if !ok2 {
+					continue
+				}
+				//todo 引用时间
+				tmp := &data_manage.EdbInfoRelation{
+					ReferObjectId:      v.ExcelInfoId,
+					ReferObjectType:    utils.EDB_RELATION_TABLE,
+					ReferObjectSubType: v.Source,
+					EdbInfoId:          v.EdbInfoId,
+					EdbName:            edbInfo.EdbName,
+					Source:             edbInfo.Source,
+					EdbCode:            edbInfo.EdbCode,
+					CreateTime:         nowTime,
+					ModifyTime:         nowTime,
+					RelationTime:       v.CreateTime,
+				}
+				tmp.RelationCode = fmt.Sprintf("%d_%d_%d_%d", tmp.EdbInfoId, tmp.ReferObjectId, tmp.ReferObjectType, tmp.ReferObjectSubType)
+				addList = append(addList, tmp)
+				existRelationMap[name] = struct{}{}
+				// 添加间接引用记录
+				if edbInfo.EdbType == 2 || edbInfo.EdbInfoType == 1 {
+					childEdbMappingIds, ok1 := calculateEdbMappingIdsMap[edbInfo.EdbInfoId]
+					if !ok1 {
+						continue
+					}
+					for _, childEdbMappingId := range childEdbMappingIds {
+						childEdbMapping, ok2 := calculateEdbMappingListMap[childEdbMappingId]
+						if !ok2 {
+							continue
+						}
+						name1 := fmt.Sprintf("%d-%d", v.ExcelInfoId, childEdbMapping.FromEdbInfoId)
+						if _, ok2 := existRelationMap[name1]; !ok2 { //如果已经被直接引用了,则无需添加到间接引用记录中
+							continue
+						}
+						tmp1 := &data_manage.EdbInfoRelation{
+							ReferObjectId:      v.ExcelInfoId,
+							ReferObjectType:    utils.EDB_RELATION_TABLE,
+							ReferObjectSubType: v.Source,
+							EdbInfoId:          childEdbMapping.FromEdbInfoId,
+							EdbName:            childEdbMapping.FromEdbName,
+							Source:             childEdbMapping.FromSource,
+							EdbCode:            childEdbMapping.FromEdbCode,
+							CreateTime:         nowTime,
+							ModifyTime:         nowTime,
+							RelationTime:       v.CreateTime,
+							RelationType:       1,
+							RootEdbInfoId:      edbInfo.EdbInfoId,
+							ChildEdbInfoId:     childEdbMapping.EdbInfoId,
+							RelationCode:       tmp.RelationCode,
+						}
+						addList = append(addList, tmp1)
+						// todo 防止重复
+					}
+				}
+
+				if len(addList) > pageSize {
+					err = data_manage.AddEdbInfoRelationMulti(addList)
+					if err != nil {
+						err = fmt.Errorf("新增引用记录失败 Err:%s", err)
+						return
+					}
+					addNum += len(addList)
+					addList = make([]*data_manage.EdbInfoRelation, 0)
+				}
+			}
+		}
+	}
+	//拿到500个数据ID,判断相关的引用记录,如果已存在则直接过滤,不存在则新增
+	if len(addList) > 0 {
+		err = data_manage.AddEdbInfoRelationMulti(addList)
+		if err != nil {
+			err = fmt.Errorf("新增引用记录失败 Err:%s", err)
+			return
+		}
+		addNum += len(addList)
+	}
+	fmt.Printf("表格指标引用记录处理完成, 新增%d条记录\n", addNum)
+	return
+}
+
+// 处理逻辑图中的指标引用
+func initSandBoxEdbRelation() {
+	fmt.Println("开始处理逻辑图中的指标引用")
+	var err error
+	var addNum int
+	defer func() {
+		if err != nil {
+			msg := fmt.Sprintf("初始化指标在逻辑图中的引用失败 initSandBoxEdbRelation  err: %v", err)
+			utils.FileLog.Info(msg)
+			fmt.Println(msg)
+			go alarm_msg.SendAlarmMsg(msg, 3)
+		}
+	}()
+	condition := " AND is_delete = 0"
+	total, err := sandbox.GetSandboxListCountByCondition(condition, []interface{}{})
+	if err != nil {
+		err = fmt.Errorf("查询逻辑图总数失败 err: %v", err)
+		return
+	}
+	if total == 0 {
+		return
+	}
+	//分页查询,每次处理500条记录
+	pageSize := 100
+	totalPage := (total + pageSize - 1) / pageSize // 使用整数除法,并添加一页以防有余数
+	addList := make([]*data_manage.EdbInfoRelation, 0)
+	//查询图表列表
+	for i := 0; i < totalPage; i += 1 {
+		startSize := i * pageSize
+		list, e := sandbox.GetSandboxListByCondition(condition, []interface{}{}, startSize, pageSize)
+		if e != nil {
+			err = fmt.Errorf("查询逻辑图列表失败 Err:%s", e)
+			return
+		}
+		if len(list) == 0 {
+			break
+		}
+
+		edbInfoIds := make([]int, 0)
+		edbSandboxMap := make(map[int][]*sandbox.Sandbox)
+		for _, v := range list {
+			if v.Content == "" {
+				continue
+			}
+			edbInfoIdsTmp, e := getSandBoxEdbIdsByContent(v.Content)
+			if e != nil {
+				continue
+				//err = fmt.Errorf("查询逻辑图关联的指标Id失败 Err:%s", e)
+				//return
+			}
+			for _, edbId := range edbInfoIdsTmp {
+				edbInfoIds = append(edbInfoIds, edbId)
+				edbSandboxMap[edbId] = append(edbSandboxMap[edbId], v)
+			}
+		}
+		if len(edbInfoIds) <= 0 {
+			continue
+		}
+		// 查询指标信息表
+		edbInfoList, e := data_manage.GetEdbInfoByIdList(edbInfoIds)
+		if e != nil {
+			err = fmt.Errorf("查询指标信息列表失败 Err:%s", e)
+			return
+		}
+		if len(edbInfoList) == 0 {
+			continue
+		}
+		// 查询计算指标信息,并且建立关联关系
+		// 查询间接引用的指标信息
+		calculateEdbMappingListMap, calculateEdbMappingIdsMap, e := GetEdbListByEdbInfoId(edbInfoList)
+		if e != nil {
+			err = fmt.Errorf("查询计算指标信息失败,%s", e.Error())
+			return
+		}
+		edbInfoMap := make(map[int]*data_manage.EdbInfo)
+		sandboxIds := make([]int, 0)
+		for _, v := range edbInfoList {
+			edbInfoMap[v.EdbInfoId] = v
+			if items, ok := edbSandboxMap[v.EdbInfoId]; ok {
+				for _, item := range items {
+					sandboxIds = append(sandboxIds, item.SandboxId)
+				}
+			}
+		}
+
+		//查询引用关系列表,
+		chartEdbRelationList, e := data_manage.GetEdbInfoRelationByReferObjectIds(sandboxIds, utils.EDB_RELATION_SANDBOX)
+		if e != nil {
+			err = fmt.Errorf("查询逻辑图引用关系列表失败 Err:%s", e)
+			return
+		}
+		existRelationMap := make(map[string]struct{})
+		for _, v := range chartEdbRelationList {
+			name := fmt.Sprintf("%d-%d", v.ReferObjectId, v.EdbInfoId)
+			existRelationMap[name] = struct{}{}
+		}
+		for edbInfoId, sandboxList := range edbSandboxMap {
+			nowTime := time.Now()
+			for _, v := range sandboxList {
+				name := fmt.Sprintf("%d-%d", v.SandboxId, edbInfoId)
+				if _, ok := existRelationMap[name]; !ok {
+					edbInfo, ok2 := edbInfoMap[edbInfoId]
+					if !ok2 {
+						continue
+					}
+					//todo 引用时间
+					tmp := &data_manage.EdbInfoRelation{
+						ReferObjectId:   v.SandboxId,
+						ReferObjectType: utils.EDB_RELATION_SANDBOX,
+						EdbInfoId:       edbInfoId,
+						EdbName:         edbInfo.EdbName,
+						Source:          edbInfo.Source,
+						EdbCode:         edbInfo.EdbCode,
+						CreateTime:      nowTime,
+						ModifyTime:      nowTime,
+						RelationTime:    v.CreateTime,
+					}
+					tmp.RelationCode = fmt.Sprintf("%d_%d_%d_%d", tmp.EdbInfoId, tmp.ReferObjectId, tmp.ReferObjectType, tmp.ReferObjectSubType)
+					addList = append(addList, tmp)
+					existRelationMap[name] = struct{}{}
+					// 添加间接引用记录
+					if edbInfo.EdbType == 2 || edbInfo.EdbInfoType == 1 {
+						childEdbMappingIds, ok1 := calculateEdbMappingIdsMap[edbInfo.EdbInfoId]
+						if !ok1 {
+							continue
+						}
+						for _, childEdbMappingId := range childEdbMappingIds {
+							childEdbMapping, ok2 := calculateEdbMappingListMap[childEdbMappingId]
+							if !ok2 {
+								continue
+							}
+							name1 := fmt.Sprintf("%d-%d", v.SandboxId, childEdbMapping.FromEdbInfoId)
+							if _, ok2 := existRelationMap[name1]; !ok2 { //如果已经被直接引用了,则无需添加到间接引用记录中
+								continue
+							}
+							tmp1 := &data_manage.EdbInfoRelation{
+								ReferObjectId:   v.SandboxId,
+								ReferObjectType: utils.EDB_RELATION_SANDBOX,
+								EdbInfoId:       childEdbMapping.FromEdbInfoId,
+								EdbName:         childEdbMapping.FromEdbName,
+								Source:          childEdbMapping.FromSource,
+								EdbCode:         childEdbMapping.FromEdbCode,
+								CreateTime:      nowTime,
+								ModifyTime:      nowTime,
+								RelationTime:    v.CreateTime,
+								RelationType:    1,
+								RootEdbInfoId:   edbInfo.EdbInfoId,
+								ChildEdbInfoId:  childEdbMapping.EdbInfoId,
+								RelationCode:    tmp.RelationCode,
+							}
+							addList = append(addList, tmp1)
+							// todo 防止重复
+						}
+					}
+					if len(addList) > pageSize {
+						err = data_manage.AddEdbInfoRelationMulti(addList)
+						if err != nil {
+							err = fmt.Errorf("新增引用记录失败 Err:%s", err)
+							return
+						}
+						addNum += len(addList)
+						addList = make([]*data_manage.EdbInfoRelation, 0)
+					}
+				}
+			}
+		}
+	}
+	//拿到500个数据ID,判断相关的引用记录,如果已存在则直接过滤,不存在则新增
+	if len(addList) > 0 {
+		err = data_manage.AddEdbInfoRelationMulti(addList)
+		if err != nil {
+			err = fmt.Errorf("新增引用记录失败 Err:%s", err)
+			return
+		}
+		addNum += len(addList)
+	}
+	fmt.Printf("逻辑图指标引用记录处理完成, 新增%d条记录\n", addNum)
+	return
+}
+
+func getSandBoxEdbIdsByContent(content string) (edbInfoIds []int, err error) {
+	var contentInfo sandbox.ContentDataStruct
+	err = json.Unmarshal([]byte(content), &contentInfo)
+	if err != nil {
+		err = fmt.Errorf("json.Unmarshal err:%s", err.Error())
+		return
+	}
+	// 遍历所有节点
+	for _, node := range contentInfo.Cells {
+		if node.Data == nil {
+			continue
+		}
+		for _, v := range node.Data.LinkData {
+			if v.Type == 1 {
+				edbInfoIds = append(edbInfoIds, v.Id)
+			}
+		}
+	}
+	return
+}
+
+func GetEdbListByEdbInfoId(edbInfoList []*data_manage.EdbInfo) (edbMappingListMap map[int]*data_manage.EdbInfoCalculateMapping, edbInfoMappingRootIdsMap map[int][]int, err error) {
+	if len(edbInfoList) == 0 {
+		return
+	}
+	edbInfoIds := make([]int, 0)
+	for _, v := range edbInfoList {
+		if v.EdbType == 2 || v.EdbInfoType == 1 {
+			edbInfoIds = append(edbInfoIds, v.EdbInfoId)
+		}
+	}
+	if len(edbInfoIds) == 0 {
+		return
+	}
+	//查询指标信息
+	allEdbMappingMap := make(map[int][]*data_manage.EdbInfoCalculateMappingInfo, 0)
+	allMappingList, e := data_manage.GetEdbInfoCalculateMappingListByEdbInfoIds(edbInfoIds)
+	if e != nil {
+		err = fmt.Errorf("GetEdbInfoCalculateMappingListByEdbInfoIds err: %s", e.Error())
+		return
+	}
+	for _, v := range allMappingList {
+		if _, ok := allEdbMappingMap[v.EdbInfoId]; !ok {
+			allEdbMappingMap[v.EdbInfoId] = make([]*data_manage.EdbInfoCalculateMappingInfo, 0)
+		}
+		allEdbMappingMap[v.EdbInfoId] = append(allEdbMappingMap[v.EdbInfoId], v)
+	}
+	//查询指标映射
+	//查询所有指标数据
+	//查询这个指标相关的mapping信息放到数组里,
+	//将得到的指标ID信息放到数组里
+	hasFindMap := make(map[int]struct{})
+	edbInfoIdMap := make(map[int]struct{})
+	edbMappingList := make([]*data_manage.EdbInfoCalculateMapping, 0)
+	edbInfoMappingRootIdsMap = make(map[int][]int, 0)
+	edbMappingMap := make(map[int]struct{})
+	for _, edbInfo := range edbInfoList {
+		if edbInfo.EdbType == 2 || edbInfo.EdbInfoType == 1 {
+			edbInfoId := edbInfo.EdbInfoId
+			edbMappingList, err = getCalculateEdbInfoByEdbInfoId(allEdbMappingMap, edbInfoId, hasFindMap, edbInfoIdMap, edbMappingList, edbMappingMap, edbInfoMappingRootIdsMap, edbInfoId)
+			if err != nil {
+				err = fmt.Errorf(" GetCalculateEdbInfoByEdbInfoId err: %s", err.Error())
+				return
+			}
+		}
+	}
+	if len(edbMappingList) == 0 {
+		return
+	}
+	// 查询指标信息
+	// 指标信息map
+	edbInfoIdList := make([]int, 0)
+	for k, _ := range edbInfoIdMap {
+		edbInfoIdList = append(edbInfoIdList, k)
+	}
+	edbMappingListMap = make(map[int]*data_manage.EdbInfoCalculateMapping)
+
+	if len(edbMappingList) > 0 {
+		for _, v := range edbMappingList {
+			edbMappingListMap[v.EdbInfoCalculateMappingId] = v
+		}
+	}
+	return
+}
+
+// getCalculateEdbInfoByEdbInfoId 计算指标追溯
+func getCalculateEdbInfoByEdbInfoId(allEdbMappingMap map[int][]*data_manage.EdbInfoCalculateMappingInfo, edbInfoId int, hasFindMap map[int]struct{}, edbInfoIdMap map[int]struct{}, edbMappingList []*data_manage.EdbInfoCalculateMapping, edbMappingMap map[int]struct{}, edbInfoMappingRootIdsMap map[int][]int, rootEdbInfoId int) (newEdbMappingList []*data_manage.EdbInfoCalculateMapping, err error) {
+	newEdbMappingList = edbMappingList
+	_, ok := hasFindMap[edbInfoId]
+	if ok {
+		return
+	}
+
+	if _, ok1 := edbInfoIdMap[edbInfoId]; !ok1 {
+		edbInfoIdMap[edbInfoId] = struct{}{}
+	}
+	edbInfoMappingList := make([]*data_manage.EdbInfoCalculateMappingInfo, 0)
+	edbInfoMappingList, ok = allEdbMappingMap[edbInfoId]
+	if !ok {
+		edbInfoMappingList, err = data_manage.GetEdbInfoCalculateMappingListByEdbInfoId(edbInfoId)
+		if err != nil {
+			err = fmt.Errorf("GetEdbInfoCalculateMappingListByEdbInfoId err: %s", err.Error())
+			return
+		}
+	}
+	hasFindMap[edbInfoId] = struct{}{}
+	if len(edbInfoMappingList) > 0 {
+		fromEdbInfoIdList := make([]int, 0)
+		edbInfoMappingIdList := make([]int, 0)
+		for _, v := range edbInfoMappingList {
+			fromEdbInfoIdList = append(fromEdbInfoIdList, v.FromEdbInfoId)
+			edbInfoMappingIdList = append(edbInfoMappingIdList, v.EdbInfoCalculateMappingId)
+			if _, ok1 := edbInfoIdMap[v.FromEdbInfoId]; !ok1 {
+				edbInfoIdMap[v.FromEdbInfoId] = struct{}{}
+			}
+			if _, ok2 := edbMappingMap[v.EdbInfoCalculateMappingId]; !ok2 {
+				edbMappingMap[v.EdbInfoCalculateMappingId] = struct{}{}
+				tmp := &data_manage.EdbInfoCalculateMapping{
+					EdbInfoCalculateMappingId: v.EdbInfoCalculateMappingId,
+					EdbInfoId:                 v.EdbInfoId,
+					Source:                    v.Source,
+					SourceName:                v.SourceName,
+					EdbCode:                   v.EdbCode,
+					FromEdbInfoId:             v.FromEdbInfoId,
+					FromEdbCode:               v.FromEdbCode,
+					FromEdbName:               v.FromEdbName,
+					FromSource:                v.FromSource,
+					FromSourceName:            v.FromSourceName,
+					FromTag:                   v.FromTag,
+					Sort:                      v.Sort,
+					CreateTime:                v.CreateTime,
+					ModifyTime:                v.ModifyTime,
+				}
+				newEdbMappingList = append(newEdbMappingList, tmp)
+
+			}
+
+			if edbInfoId != v.FromEdbInfoId && (v.FromEdbType == 2 || v.FromEdbInfoType == 1) {
+				// 查过了就不查了
+				if _, ok2 := hasFindMap[v.FromEdbInfoId]; !ok2 {
+					newEdbMappingList, err = getCalculateEdbInfoByEdbInfoId(allEdbMappingMap, v.FromEdbInfoId, hasFindMap, edbInfoIdMap, newEdbMappingList, edbMappingMap, edbInfoMappingRootIdsMap, rootEdbInfoId)
+					if err != nil {
+						err = fmt.Errorf("traceEdbInfoByEdbInfoId err: %s", err.Error())
+						return
+					}
+				}
+			}
+			hasFindMap[v.FromEdbInfoId] = struct{}{}
+		}
+		edbInfoMappingRootIdsMap[rootEdbInfoId] = append(edbInfoMappingRootIdsMap[rootEdbInfoId], edbInfoMappingIdList...)
+	}
+
+	return
+}

+ 36 - 3
services/eta_bridge/eta_bridge.go

@@ -5,6 +5,7 @@ import (
 	"errors"
 	"eta/eta_task/utils"
 	"fmt"
+	"github.com/rdlucklib/rdluck_tools/paging"
 	"io"
 	"net/http"
 	"strings"
@@ -109,10 +110,10 @@ func HttpEtaBridgeGet(urlStr string) (bResult []byte, err error, errMsg string)
 		return
 	}
 
-	postUrl := utils.EtaBridgeUrl + "/api" + urlStr
+	getUrl := utils.EtaBridgeUrl + "/api" + urlStr
 
 	client := &http.Client{}
-	req, e := http.NewRequest("GET", postUrl, nil)
+	req, e := http.NewRequest("GET", getUrl, nil)
 	if e != nil {
 		err = fmt.Errorf("http create request err: %s", e.Error())
 		return
@@ -150,7 +151,7 @@ func HttpEtaBridgeGet(urlStr string) (bResult []byte, err error, errMsg string)
 	result := new(BaseEtaBridgeDataResp)
 	if e = json.Unmarshal(bResult, &result); e != nil {
 		err = fmt.Errorf("result unmarshal err: %s\nresult: %s", e.Error(), string(bResult))
-		utils.FileLog.Info("桥接服务get请求失败:\n" + string(bResult))
+		utils.FileLog.Info("桥接服务get请求失败,url", getUrl, ":\n", string(bResult))
 		return
 	}
 	if result.Code != 200 {
@@ -161,3 +162,35 @@ func HttpEtaBridgeGet(urlStr string) (bResult []byte, err error, errMsg string)
 
 	return
 }
+
+// EtaBridgeDataRespAndBusinessData 基础返回参数
+type EtaBridgeDataRespAndBusinessData struct {
+	Code int                 `json:"code" description:"状态码"`
+	Msg  string              `json:"msg" description:"提示信息"`
+	Data GetBusinessDataResp `json:"data" description:"返回数据"`
+}
+
+type GetBusinessDataResp struct {
+	List   []PushBusinessIndex
+	Paging *paging.PagingItem `description:"分页数据"`
+}
+
+// PushBusinessIndex
+// @Description:  添加外部指标(商家)请求
+type PushBusinessIndex struct {
+	IndexCode            string            `description:"指标编码"`
+	IndexName            string            `description:"指标名称"`
+	Unit                 string            `description:"单位"`
+	Frequency            string            `description:"频度"`
+	SourceName           string            `description:"数据来源名称"`
+	Remark               string            `description:"备注字段"`
+	DetailDataCreateTime string            `description:"明细数据入库时间"`
+	DataList             []AddBusinessData `description:"指标数据"`
+}
+
+// AddBusinessData
+// @Description: 外部指标(商家系统)数据
+type AddBusinessData struct {
+	Value float64 `description:"值"`
+	Date  string  `description:"日期"`
+}

+ 12 - 0
services/eta_bridge/handle_data.go

@@ -58,6 +58,10 @@ func handleInsert(edbUpdateLog *data_manage.EdbUpdateLog) (pushIndexData *PushIn
 		if edbInfo.EdbType == 2 {
 			return
 		}
+		// 自有数据不处理
+		if edbInfo.Source == utils.DATA_SOURCE_BUSINESS {
+			return
+		}
 
 		// 获取数据源中指标的基础信息
 		origInfo := getOrigInfo(edbInfo.Source, edbInfo.SubSource, edbInfo.EdbCode, edbInfo.EdbName)
@@ -192,6 +196,10 @@ func handleDelete(edbUpdateLog *data_manage.EdbUpdateLog) (pushIndexData *PushIn
 		if edbInfo.EdbType == 2 {
 			return
 		}
+		// 自有数据不处理
+		if edbInfo.Source == utils.DATA_SOURCE_BUSINESS {
+			return
+		}
 
 		// 获取数据源中指标的基础信息
 		origInfo := getOrigInfo(edbInfo.Source, edbInfo.SubSource, edbInfo.EdbCode, edbInfo.EdbName)
@@ -327,6 +335,10 @@ func handleUpdate(edbUpdateLog *data_manage.EdbUpdateLog) (pushIndexData *PushIn
 		if oldEdbInfo.EdbType == 2 {
 			return
 		}
+		// 自有数据不处理
+		if oldEdbInfo.Source == utils.DATA_SOURCE_BUSINESS {
+			return
+		}
 
 		var newEdbInfo *data_manage.EdbInfoItem
 		err = json.Unmarshal([]byte(newData), &newEdbInfo)

+ 181 - 0
services/eta_bridge/xy.go

@@ -5,9 +5,11 @@ import (
 	"encoding/json"
 	"eta/eta_task/models/data_manage"
 	"eta/eta_task/services/alarm_msg"
+	"eta/eta_task/services/eta_hub"
 	"eta/eta_task/utils"
 	"fmt"
 	"github.com/rdlucklib/rdluck_tools/uuid"
+	"net/url"
 	"strings"
 	"sync"
 	"time"
@@ -519,3 +521,182 @@ func min(a, b int) int {
 	}
 	return b
 }
+
+// 同步crm指标信息锁
+var lockGetCrmIndex sync.Mutex
+
+// SyncXyCrmIndex
+// @Description: 定时同步CRM指标信息
+// @author: Roc
+// @datetime 2024-5-22 10:46:08
+// @param cont context.Context
+// @return err error
+func SyncXyCrmIndex(cont context.Context) (err error) {
+	lockGetCrmIndex.Lock()
+	errMsgList := make([]string, 0)
+	defer func() {
+		if err != nil {
+			tips := "SyncXyCrmIndex-定时同步CRM数据到ETA平台失败, ErrMsg:\n" + err.Error()
+			utils.FileLog.Info(tips)
+			go alarm_msg.SendAlarmMsg(tips, 3)
+		}
+		if len(errMsgList) > 0 {
+			tips := "SyncXyCrmIndex-定时同步CRM数据到ETA平台失败, ErrMsg:\n" + strings.Join(errMsgList, "\n")
+			utils.FileLog.Info(tips)
+			go alarm_msg.SendAlarmMsg(tips, 3)
+		}
+		lockGetCrmIndex.Unlock()
+		fmt.Println("end SyncXyCrmIndex")
+	}()
+
+	// 未配置资产包合数据分区,那么就不执行
+	if utils.SyncCrmAssetPkgCd == `` || utils.SyncCrmDataSourceType == `` {
+		return
+	}
+
+	var lastUpdateTimeStr string                                   // 上一次更新的时间
+	nowTimeStr := time.Now().Format(utils.FormatDateTimeUnSpaceV2) // 这次更新的时间
+
+	key := data_manage.CrmIndexLastUpdateTime
+	sysInteractionLog, err := data_manage.GetBusinessSysInteractionLogByKey(key)
+	if err != nil {
+		if err.Error() != utils.ErrNoRow() {
+			return
+		}
+		//lastUpdateTime := time.Now().Format("2006-01-02 15:04:05")
+	} else {
+		if sysInteractionLog.InteractionVal != `` {
+			lastUpdateTimeStr = sysInteractionLog.InteractionVal
+		}
+	}
+
+	syncCrmAssetPkgCd := utils.SyncCrmAssetPkgCd
+	syncCrmAssetPkgCdList := strings.Split(syncCrmAssetPkgCd, ",")
+
+	for _, assetPkgCd := range syncCrmAssetPkgCdList {
+		err, errMsgList = syncCrmIndex(assetPkgCd, 1, utils.SyncCrmIndexNum, lastUpdateTimeStr)
+	}
+
+	// 修改最后的更新时间
+	modifyCrmIndexLastUpdateTime(nowTimeStr)
+
+	return
+}
+
+// syncCrmIndex
+// @Description: 开始同步CRM指标信息
+// @author: Roc
+// @datetime 2024-05-17 15:55:11
+// @param assetPkgCd string
+// @param currIndex int
+// @param pageSize int
+// @param lastUpdateTimeStr string
+// @return err error
+// @return errMsgList []string
+func syncCrmIndex(assetPkgCd string, currIndex, pageSize int, baseLastUpdateTimeStr string) (err error, errMsgList []string) {
+	errMsgList = make([]string, 0)
+
+	lastUpdateTimeStr := baseLastUpdateTimeStr
+	if lastUpdateTimeStr != `` {
+		lastUpdateTimeStr = url.QueryEscape(lastUpdateTimeStr)
+	}
+	uri := fmt.Sprintf("%s/getCrmData?index_pkg_code=%s&data_source_type=%s&current_index=%d&page_size=%d&detail_last_update_start_time=%s", utils.SyncCrmIndexPath, assetPkgCd, utils.SyncCrmDataSourceType, currIndex, pageSize, lastUpdateTimeStr)
+	bResult, err, _ := HttpEtaBridgeGet(uri)
+	if err != nil {
+		return
+	}
+
+	result := new(EtaBridgeDataRespAndBusinessData)
+	err = json.Unmarshal(bResult, &result)
+	if err != nil {
+		err = fmt.Errorf("result unmarshal err: %s\nresult: %s", err.Error(), string(bResult))
+		utils.FileLog.Info("桥接服务get请求失败:\n" + string(bResult))
+		return
+	}
+
+	//totalPage := result.Data.Paging.Pages
+
+	for _, v := range result.Data.List {
+		tmpErr := pushCrmDataToHub(v)
+		if tmpErr != nil {
+			errMsgList = append(errMsgList, tmpErr.Error())
+		}
+
+	}
+
+	// 如果还有下一页,那么就继续请求下一页
+	if currIndex < result.Data.Paging.Pages {
+		_, tmpErrMsgList := syncCrmIndex(assetPkgCd, currIndex+1, utils.SyncCrmIndexNum, baseLastUpdateTimeStr)
+		errMsgList = append(errMsgList, tmpErrMsgList...)
+	}
+
+	return
+}
+
+// pushCrmDataToHub
+// @Description: 调用hub服务,将数据推送到eta
+// @author: Roc
+// @datetime 2024-05-17 15:55:24
+// @param data interface{}
+// @return err error
+func pushCrmDataToHub(data interface{}) (err error) {
+	uri := `/edb/push`
+	_, err, _ = eta_hub.HttpEtaHubPost(uri, data)
+
+	//result := new(EtaBridgeDataRespAndBusinessData)
+	//err = json.Unmarshal(bResult, &result)
+	//if err != nil {
+	//	err = fmt.Errorf("result unmarshal err: %s\nresult: %s", err.Error(), string(bResult))
+	//	utils.FileLog.Info("桥接服务get请求失败:\n" + string(bResult))
+	//	return
+	//}
+
+	return
+}
+
+// modifyCrmIndexLastUpdateTime
+// @Description: 修改crm指标的最近拉取的时间
+// @author: Roc
+// @datetime 2024-05-17 11:32:32
+// @param fileName string
+// @param position uint32
+// @return err error
+func modifyCrmIndexLastUpdateTime(lastUpdateTime string) {
+	var err error
+	defer func() {
+		if err != nil {
+			utils.FileLog.Error("修改binlog文件名称和位置异常,lastUpdateTime", lastUpdateTime, ",err:", err)
+		}
+	}()
+
+	// fileName 变更
+	key := data_manage.CrmIndexLastUpdateTime
+	fileNameLog, err := data_manage.GetBusinessSysInteractionLogByKey(key)
+	if err != nil {
+		if err.Error() != utils.ErrNoRow() {
+			return
+		}
+		err = nil
+		fileNameLog = &data_manage.BusinessSysInteractionLog{
+			//ID:             0,
+			InteractionKey: key,
+			InteractionVal: lastUpdateTime,
+			Remark:         "crm拉取数据的最近更新时间",
+			ModifyTime:     time.Now(),
+			CreateTime:     time.Now(),
+		}
+		err = fileNameLog.Create()
+		if err != nil {
+			return
+		}
+	} else {
+		fileNameLog.InteractionVal = lastUpdateTime
+		fileNameLog.ModifyTime = time.Now()
+		err = fileNameLog.Update([]string{"InteractionVal", "ModifyTime"})
+		if err != nil {
+			return
+		}
+	}
+
+	return
+}

+ 194 - 0
services/eta_hub/edb.go

@@ -0,0 +1,194 @@
+package eta_hub
+
+import (
+	"encoding/json"
+	"errors"
+	"eta/eta_task/utils"
+	"fmt"
+	"io"
+	"net/http"
+	"sort"
+	"strings"
+	"time"
+)
+
+// BaseEtaHubDataResp 基础返回参数
+type BaseEtaHubDataResp struct {
+	Ret         int
+	Msg         string
+	ErrMsg      string
+	ErrCode     string
+	Data        interface{}
+	Success     bool `description:"true 执行成功,false 执行失败"`
+	IsSendEmail bool `json:"-" description:"true 发送邮件,false 不发送邮件"`
+	IsAddLog    bool `json:"-" description:"true 新增操作日志,false 不新增操作日志" `
+}
+
+// HttpEtaHubPost
+// @Description: eta-bridge的post请求
+// @author: Roc
+// @datetime 2024-02-28 16:55:02
+// @param urlStr string
+// @param postData string
+// @param param interface{}
+// @return bResult []byte
+// @return err error
+// @return errMsg string
+func HttpEtaHubPost(urlStr string, param interface{}) (bResult []byte, err error, errMsg string) {
+	if utils.EtaHubUrl == "" {
+		errMsg = `未配置第三方的桥接服务地址`
+		err = errors.New(errMsg)
+		return
+	}
+	data, e := json.Marshal(param)
+	if e != nil {
+		err = fmt.Errorf("data json marshal err: %s", e.Error())
+		return
+	}
+
+	postUrl := utils.EtaHubUrl + "/v1" + urlStr
+
+	body := io.NopCloser(strings.NewReader(string(data)))
+	client := &http.Client{}
+	req, e := http.NewRequest("POST", postUrl, body)
+	if e != nil {
+		err = fmt.Errorf("http create request err: %s", e.Error())
+		return
+	}
+
+	// 随机字符串
+	nonce := utils.GetRandStringNoSpecialChar(16)
+	timestamp := fmt.Sprint(time.Now().Second())
+	sign := GetSign(nonce, timestamp)
+
+	contentType := "application/json;charset=utf-8"
+	req.Header.Set("Content-Type", contentType)
+	req.Header.Set("nonce", nonce)
+	req.Header.Set("timestamp", timestamp)
+	req.Header.Set("appid", utils.APPID)
+	req.Header.Set("signature", sign)
+
+	resp, e := client.Do(req)
+	if e != nil {
+		err = fmt.Errorf("http client do err: %s", e.Error())
+		return
+	}
+	defer func() {
+		_ = resp.Body.Close()
+	}()
+	bResult, e = io.ReadAll(resp.Body)
+	if e != nil {
+		err = fmt.Errorf("resp body read err: %s", e.Error())
+		return
+	}
+	if len(bResult) == 0 {
+		err = fmt.Errorf("resp body is empty")
+		return
+	}
+
+	result := new(BaseEtaHubDataResp)
+	if e = json.Unmarshal(bResult, &result); e != nil {
+		err = fmt.Errorf("result unmarshal err: %s\nresult: %s", e.Error(), string(bResult))
+		utils.FileLog.Info("桥接服务post请求失败:\n" + string(bResult))
+		return
+	}
+	if result.Ret != 200 {
+		errMsg = result.Msg
+		err = fmt.Errorf("result: %s", string(bResult))
+		return
+	}
+
+	return
+}
+
+// HttpEtaHubGet
+// @Description: eta-bridge的get请求
+// @author: Roc
+// @datetime 2024-02-28 16:55:02
+// @param urlStr string
+// @param postData string
+// @return bResult []byte
+// @return err error
+// @return errMsg string
+func HttpEtaHubGet(urlStr string) (bResult []byte, err error, errMsg string) {
+	if utils.EtaHubUrl == "" {
+		errMsg = `未配置第三方的桥接服务地址`
+		err = errors.New(errMsg)
+		return
+	}
+
+	postUrl := utils.EtaHubUrl + "/v1" + urlStr
+
+	client := &http.Client{}
+	req, e := http.NewRequest("GET", postUrl, nil)
+	if e != nil {
+		err = fmt.Errorf("http create request err: %s", e.Error())
+		return
+	}
+
+	contentType := "application/json;charset=utf-8"
+	// 随机字符串
+	nonce := utils.GetRandStringNoSpecialChar(16)
+	timestamp := fmt.Sprint(time.Now().Second())
+	sign := GetSign(nonce, timestamp)
+
+	req.Header.Set("Content-Type", contentType)
+	req.Header.Set("nonce", nonce)
+	req.Header.Set("timestamp", timestamp)
+	req.Header.Set("appid", utils.APPID)
+	req.Header.Set("signature", sign)
+
+	resp, e := client.Do(req)
+	if e != nil {
+		err = fmt.Errorf("http client do err: %s", e.Error())
+		return
+	}
+	defer func() {
+		_ = resp.Body.Close()
+	}()
+	bResult, e = io.ReadAll(resp.Body)
+	if e != nil {
+		err = fmt.Errorf("resp body read err: %s", e.Error())
+		return
+	}
+	if len(bResult) == 0 {
+		err = fmt.Errorf("resp body is empty")
+		return
+	}
+
+	result := new(BaseEtaHubDataResp)
+	if e = json.Unmarshal(bResult, &result); e != nil {
+		err = fmt.Errorf("result unmarshal err: %s\nresult: %s", e.Error(), string(bResult))
+		utils.FileLog.Info("桥接服务get请求失败:\n" + string(bResult))
+		return
+	}
+	if result.Ret != 200 {
+		errMsg = result.Msg
+		err = fmt.Errorf("result: %s", string(bResult))
+		return
+	}
+
+	return
+}
+
+func GetSign(nonce, timestamp string) (sign string) {
+	signStrMap := map[string]string{
+		"nonce":     nonce,
+		"timestamp": timestamp,
+		"appid":     utils.APPID,
+	}
+	keys := make([]string, 0, len(signStrMap))
+	for k := range signStrMap {
+		keys = append(keys, k)
+	}
+	sort.Strings(keys)
+	var signStr string
+	for _, k := range keys {
+		signStr += k + "=" + signStrMap[k] + "&"
+	}
+	signStr = strings.Trim(signStr, "&")
+	//fmt.Println("signStr:" + signStr)
+	sign = utils.HmacSha256ToBase64(utils.SECRET, signStr)
+	//fmt.Println("sign:" + sign)
+	return
+}

+ 4 - 0
services/task.go

@@ -53,6 +53,10 @@ func releaseTask() {
 	configRefreshData := task.NewTask("syncBaseDataExt", "0 */30 * * * * ", ConfigRefreshData)
 	task.AddTask("configRefreshData", configRefreshData)
 
+	// 定时禁用钢联化工和wind指标的刷新状态
+	disableEdbRefresh := task.NewTask("disableEdbRefresh", "0 0 10 * * *", DisableEdbRefresh)
+	task.AddTask("disableEdbRefresh", disableEdbRefresh)
+
 	//同步弘则数据库中来自,钢联,隆众,有色,人工等基础数据--每隔五分钟,同步一次最新数据
 	syncBaseData := task.NewTask("syncBaseData", "0 */5 * * * * ", SyncBaseData)
 	task.AddTask("syncBaseData", syncBaseData)

+ 10 - 0
services/task_xy.go

@@ -47,4 +47,14 @@ func XyTask() {
 		syncIndex := task.NewTask("syncIndex", syncIndexTime, eta_bridge.SyncIndex)
 		task.AddTask("定时同步指标信息", syncIndex)
 	}
+
+	if utils.SyncCrmIndexPath != `` {
+		// 每小时同步一次指标列表
+		syncIndexTime := utils.SyncCrmIndexTime
+		if syncIndexTime == `` {
+			syncIndexTime = "0 0 * * * *"
+		}
+		syncXyCrmIndex := task.NewTask("syncXyCrmIndex", syncIndexTime, eta_bridge.SyncXyCrmIndex)
+		task.AddTask("定时同步crm指标信息", syncXyCrmIndex)
+	}
 }

+ 16 - 0
utils/common.go

@@ -4,6 +4,7 @@ import (
 	"crypto/hmac"
 	"crypto/md5"
 	"crypto/sha1"
+	"crypto/sha256"
 	"encoding/base64"
 	"encoding/hex"
 	"encoding/json"
@@ -935,3 +936,18 @@ func GetTimeSubDay(t1, t2 time.Time) int {
 
 	return day
 }
+
+// HmacSha256 计算HmacSha256
+// key 是加密所使用的key
+// data 是加密的内容
+func HmacSha256(key string, data string) []byte {
+	mac := hmac.New(sha256.New, []byte(key))
+	_, _ = mac.Write([]byte(data))
+
+	return mac.Sum(nil)
+}
+
+// HmacSha256ToBase64 将加密后的二进制转Base64字符串
+func HmacSha256ToBase64(key string, data string) string {
+	return base64.URLEncoding.EncodeToString(HmacSha256(key, data))
+}

+ 35 - 9
utils/config.go

@@ -131,6 +131,15 @@ var (
 	SyncIndexPath         string // 桥接服务-指标同步服务地址
 	SyncIndexTime         string // 桥接服务-指标同步的时间配置
 	SyncIndexClassifyTime string // 桥接服务-指标分类同步的时间配置
+	SyncCrmIndexPath      string // 桥接服务-crm指标同步服务地址
+	SyncCrmIndexTime      string // 桥接服务-crm指标同步的时间配置
+	SyncCrmAssetPkgCd     string // 桥接服务-crm资产包配置
+	SyncCrmDataSourceType string // 桥接服务-crm内部来源系统参数配置
+	SyncCrmIndexNum       int    // 桥接服务-每次同步crm数据的数量
+)
+
+var (
+	EtaHubUrl string // 公共服务地址
 )
 
 var (
@@ -275,15 +284,32 @@ func init() {
 
 	// 桥接服务
 	{
-		EtaBridgeUrl = config["eta_bridge_url"]                    // 桥接服务地址
-		EtaBridgeAppNameEn = config["eta_bridge_app_name_en"]      // 桥接服务英文名称-鉴权用
-		EtaBridgeMd5Key = config["eta_bridge_md5_key"]             // 桥接服务Md5密钥-鉴权用
-		EtaBridgeDesKey = config["eta_bridge_des_key"]             // 桥接服务Des密钥-解密数据用
-		SyncUserPath = config["sync_user_path"]                    // 桥接服务-用户同步服务地址
-		SyncUserTime = config["sync_user_time"]                    // 桥接服务-用户同步的时间配置
-		SyncIndexPath = config["sync_index_path"]                  // 桥接服务-指标同步服务地址
-		SyncIndexTime = config["sync_index_time"]                  // 桥接服务-指标同步的时间配置
-		SyncIndexClassifyTime = config["sync_index_classify_time"] // 桥接服务-指标分类同步的时间配置
+		EtaBridgeUrl = config["eta_bridge_url"]                     // 桥接服务地址
+		EtaBridgeAppNameEn = config["eta_bridge_app_name_en"]       // 桥接服务英文名称-鉴权用
+		EtaBridgeMd5Key = config["eta_bridge_md5_key"]              // 桥接服务Md5密钥-鉴权用
+		EtaBridgeDesKey = config["eta_bridge_des_key"]              // 桥接服务Des密钥-解密数据用
+		SyncUserPath = config["sync_user_path"]                     // 桥接服务-用户同步服务地址
+		SyncUserTime = config["sync_user_time"]                     // 桥接服务-用户同步的时间配置
+		SyncIndexPath = config["sync_index_path"]                   // 桥接服务-指标同步服务地址
+		SyncIndexTime = config["sync_index_time"]                   // 桥接服务-指标同步的时间配置
+		SyncIndexClassifyTime = config["sync_index_classify_time"]  // 桥接服务-指标分类同步的时间配置
+		SyncCrmIndexPath = config["sync_crm_index_path"]            // 桥接服务-crm指标同步服务地址
+		SyncCrmIndexTime = config["sync_crm_index_time"]            // 桥接服务-crm指标同步的时间配置
+		SyncCrmAssetPkgCd = config["sync_crm_asset_pkg_cd"]         // 桥接服务-crm资产包配置
+		SyncCrmDataSourceType = config["sync_crm_data_source_type"] // 桥接服务-crm内部来源系统参数配置
+
+		syncCrmIndexNumStr := config["sync_crm_index_num"] // 桥接服务-每次同步crm数据的数量
+		if syncCrmIndexNumStr != `` {
+			SyncCrmIndexNum, _ = strconv.Atoi(syncCrmIndexNumStr)
+		}
+		if SyncCrmIndexNum <= 0 {
+			SyncCrmIndexNum = 2000
+		}
+	}
+
+	// 公共服务
+	{
+		EtaHubUrl = config["eta_hub_url"] // 公共服务地址
 	}
 
 	HzDataApi = config["hz_data_api"]

+ 47 - 13
utils/constants.go

@@ -2,19 +2,20 @@ package utils
 
 // 常量定义
 const (
-	FormatTime             = "15:04:05"                //时间格式
-	FormatDate             = "2006-01-02"              //日期格式
-	FormatDateUnSpace      = "20060102"                //日期格式
-	FormatDateTime         = "2006-01-02 15:04:05"     //完整时间格式
-	HlbFormatDateTime      = "2006-01-02_15:04:05.999" //完整时间格式
-	FormatDateTimeMinute   = "2006-01-02 15:04"        //时间格式只精确到分钟
-	FormatDateTimeUnSpace  = "20060102150405"          //完整时间格式
-	FormatMonthDateUnSpace = "200601"                  //年月格式
-	PageSize15             = 15                        //列表页每页数据量
-	PageSize5              = 5
-	PageSize10             = 10
-	PageSize20             = 20
-	PageSize30             = 30
+	FormatTime              = "15:04:05"                //时间格式
+	FormatDate              = "2006-01-02"              //日期格式
+	FormatDateUnSpace       = "20060102"                //日期格式
+	FormatDateTime          = "2006-01-02 15:04:05"     //完整时间格式
+	HlbFormatDateTime       = "2006-01-02_15:04:05.999" //完整时间格式
+	FormatDateTimeMinute    = "2006-01-02 15:04"        //时间格式只精确到分钟
+	FormatDateTimeUnSpace   = "20060102150405"          //完整时间格式
+	FormatDateTimeUnSpaceV2 = "20060102 15:04:05"       //完整时间格式,日期与时间中间空格隔开
+	FormatMonthDateUnSpace  = "200601"                  //年月格式
+	PageSize15              = 15                        //列表页每页数据量
+	PageSize5               = 5
+	PageSize10              = 10
+	PageSize20              = 20
+	PageSize30              = 30
 )
 
 // 手机号,电子邮箱正则
@@ -103,6 +104,7 @@ const (
 	DATA_SOURCE_GFEX                                 = 78       // 广州期货交易所->78
 	DATA_SOURCE_ICPI                                 = 79       // ICPI消费价格指数->79
 	DATA_SOURCE_BLOOMBERG                            = 83       // bloomberg彭博数据
+	DATA_SOURCE_BUSINESS                             = 84       // 来源于自有数据
 )
 
 // 数据刷新频率
@@ -154,3 +156,35 @@ const (
 
 // 已经处理了的变更id
 const CACHE_EDB_UPDATE_LOG_ID = "eta:edb_update_log:id"
+
+// 指标引用对象
+const (
+	EDB_RELATION_CHART    = 1 // 图表
+	EDB_RELATION_SANDBOX  = 2 // ETA逻辑
+	EDB_RELATION_CALENDAR = 3 // 事件日历
+	EDB_RELATION_TABLE    = 4 // 表格
+)
+
+// 图表类型
+const (
+	CHART_SOURCE_DEFAULT                         = 1
+	CHART_SOURCE_FUTURE_GOOD                     = 2
+	CHART_SOURCE_CORRELATION                     = 3  // 相关性图表
+	CHART_SOURCE_ROLLING_CORRELATION             = 4  // 滚动相关性图表
+	CHART_SOURCE_FUTURE_GOOD_PROFIT              = 5  // 商品利润曲线
+	CHART_SOURCE_LINE_EQUATION                   = 6  // 拟合方程图表
+	CHART_SOURCE_LINE_FEATURE_STANDARD_DEVIATION = 7  // 统计特征-标准差图表
+	CHART_SOURCE_LINE_FEATURE_PERCENTILE         = 8  // 统计特征-百分位图表
+	CHART_SOURCE_LINE_FEATURE_FREQUENCY          = 9  // 统计特征-频率分布图表
+	CHART_SOURCE_CROSS_HEDGING                   = 10 // 跨品种分析图表
+	CHART_SOURCE_BALANCE_EXCEL                   = 11 // 平衡表图表
+)
+
+// ETA表格
+const (
+	EXCEL_DEFAULT         = 1 // 自定义excel
+	TIME_TABLE            = 2 // 时间序列表格
+	MIXED_TABLE           = 3 // 混合表格
+	CUSTOM_ANALYSIS_TABLE = 4 // 自定义分析表格
+	BALANCE_TABLE         = 5 // 平衡表
+)