Browse Source

Merge branch 'debug' of http://8.136.199.33:3000/eta_server/eta_task into bzq/mysteel_custom_debug

zqbao 8 months ago
parent
commit
c7a45e164f

+ 59 - 0
controllers/data_ini.go

@@ -0,0 +1,59 @@
+package controllers
+
+import (
+	"eta/eta_task/models"
+	"eta/eta_task/services"
+	"eta/eta_task/utils"
+	"github.com/beego/beego/v2/server/web"
+	"time"
+)
+
+type DataInitController struct {
+	web.Controller
+}
+
+// InitEdbRelation
+// @Title 初始化历史的图表、表格等引用记录
+// @Description 初始化历史的图表、表格等引用记录
+// @Param	request	body fe_calendar.FeCalendarMatterSaveReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /relation_init [get]
+func (c *DataInitController) InitEdbRelation() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	cacheKey := "eta_task:InitEdbRelation"
+	deleteCache := true
+	defer func() {
+		if deleteCache {
+			utils.Rc.Delete(cacheKey)
+		}
+	}()
+	if !utils.Rc.SetNX(cacheKey, 1, 5*time.Minute) {
+		deleteCache = false
+		br.Msg = `系统处理中,请稍后重试!`
+		return
+	}
+	services.InitChartEdbRelation()
+	services.InitChartCrossVariety()
+	services.InitCalendarIndicatorRelation()
+	services.InitSandBoxEdbRelation()
+	services.InitExcelEdbRelation()
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "处理成功"
+}
+
+func (c *DataInitController) DisableEdbRefresh() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "处理成功"
+}

+ 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:"指标库间隔天数未引用则停用"`
+}

+ 23 - 0
models/data_manage/base_from_mysteel_chemical_index.go

@@ -66,3 +66,26 @@ func GetBaseFromMysteelChemicalIndexItems(frequencyList []string) (items []*Base
 	_, err = o.Raw(sql, frequencyList).QueryRows(&items)
 	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
+}

+ 115 - 0
models/data_manage/chart_edb_mapping.go

@@ -0,0 +1,115 @@
+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
+}
+
+type ChartEdbInfoMapping struct {
+	EdbInfoId           int     `description:"指标id"`
+	SourceName          string  `description:"来源名称"`
+	Source              int     `description:"来源id"`
+	SubSource           int     `description:"来源id"`
+	EdbCode             string  `description:"指标编码"`
+	EdbName             string  `description:"指标名称"`
+	EdbAliasName        string  `description:"指标名称(别名)"`
+	EdbNameEn           string  `description:"英文指标名称"`
+	EdbAliasNameEn      string  `description:"英文指标名称(别名)"`
+	EdbType             int     `description:"指标类型:1:基础指标,2:计算指标"`
+	Frequency           string  `description:"频率"`
+	FrequencyEn         string  `description:"英文频率"`
+	Unit                string  `description:"单位"`
+	UnitEn              string  `description:"英文单位"`
+	StartDate           string  `description:"起始日期"`
+	EndDate             string  `description:"终止日期"`
+	ModifyTime          string  `description:"指标最后更新时间"`
+	ChartEdbMappingId   int     `description:"图表指标id"`
+	ChartInfoId         int     `description:"图表id"`
+	MaxData             float64 `description:"上限"`
+	MinData             float64 `description:"下限"`
+	IsOrder             bool    `description:"true:正序,false:逆序"`
+	IsAxis              int     `description:"1:左轴,0:右轴"`
+	EdbInfoType         int     `description:"1:标准指标,0:领先指标"`
+	EdbInfoCategoryType int     `description:"0:普通指标,1:预测指标"`
+	LeadValue           int     `description:"领先值"`
+	LeadUnit            string  `description:"领先单位"`
+	LeadUnitEn          string  `description:"领先英文单位"`
+	ChartStyle          string  `description:"图表类型"`
+	ChartColor          string  `description:"颜色"`
+	PredictChartColor   string  `description:"预测数据的颜色"`
+	ChartWidth          float64 `description:"线条大小"`
+	ChartType           int     `description:"生成样式:1:曲线图,2:季节性图,3:面积图,4:柱状图,5:散点图,6:组合图,7:柱方图,8:商品价格曲线图,9:相关性图"`
+	LatestDate          string  `description:"数据最新日期"`
+	LatestValue         float64 `description:"数据最新值"`
+	MoveLatestDate      string  `description:"移动后的数据最新日期"`
+	UniqueCode          string  `description:"指标唯一编码"`
+	MinValue            float64 `json:"-" description:"最小值"`
+	MaxValue            float64 `json:"-" description:"最大值"`
+	DataList            interface{}
+	IsNullData          bool    `json:"-" description:"是否空数据"`
+	MappingSource       int     `description:"1:ETA图库;2:商品价格曲线"`
+	RegionType          string  `description:"交易所来源,海外还是国内" json:"-"`
+	ClassifyId          int     `description:"分类id"`
+	SubSourceName       string  `description:"子数据来源名称"`
+	IndicatorCode       string  `description:"指标代码"`
+	IsConvert           int     `description:"是否数据转换 0不转 1转"`
+	ConvertType         int     `description:"数据转换类型 1乘 2除 3对数"`
+	ConvertValue        float64 `description:"数据转换值"`
+	ConvertUnit         string  `description:"数据转换单位"`
+	ConvertEnUnit       string  `description:"数据转换单位"`
+	IsJoinPermission    int     `description:"是否加入权限管控,0:不加入;1:加入;默认:0"`
+	HaveOperaAuth       bool    `description:"是否有数据权限,默认:false"`
+}
+
+func GetRelationEdbInfoListMappingByCondition(condition string, pars []interface{}) (item []*ChartEdbInfoMapping, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT a.* FROM edb_info AS a 
+	JOIN edb_info_calculate_mapping AS b on a.edb_info_id = b.edb_info_id WHERE 1=1 `
+	if condition != "" {
+		sql += condition
+	}
+	_, err = o.Raw(sql, pars).QueryRows(&item)
+	return
+}

+ 11 - 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,8 @@ type ChartInfo struct {
 	ChartImage      string `description:"图表图片"`
 	Sort            int    `description:"排序字段,数字越小越排前面"`
 	EdbEndDate      string `description:"指标最后更新日期"`
+	Source          int    `description:"1:ETA图库;2:商品价格曲线"`
+	ExtraConfig     string `description:"图表额外配置,json数据"`
 }
 
 func GetAllChartInfo() (list []*ChartInfo, err error) {
@@ -51,3 +54,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
+}

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

@@ -0,0 +1,55 @@
+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
+}
+
+// ChartConfigReq
+// @Description: 跨品种分析的图表配置
+type ChartConfigReq struct {
+	TagX           int               `description:"X轴的标签ID"`
+	TagY           int               `description:"Y轴的标签ID"`
+	CalculateValue int               `description:"计算窗口"`
+	CalculateUnit  string            `description:"计算频度"`
+	DateConfigList []ChartConfigDate `description:"日期配置列表"`
+	VarietyList    []int             `description:"品种id列表"`
+	PercentType    int               `description:"百分位:0-数据区间(兼容历史数据); 1-数据个数;"`
+}
+
+// ChartConfigDate
+// @Description: 跨品种分析的日期配置
+type ChartConfigDate struct {
+	DateType int    `description:"日期类型:1-最新日期;2-N天前;3-固定日期"`
+	Num      int    `description:"N天前的N值"`
+	FixDate  string `description:"固定日期的日期"`
+	ShowTips int    `description:"是否显示标注:0-否;1-是"`
+}

+ 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 []*EdbInfo, 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
+}

+ 176 - 0
models/data_manage/factor_edb_series_chart_mapping.go

@@ -0,0 +1,176 @@
+package data_manage
+
+import (
+	"eta/eta_task/utils"
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
+	"strings"
+	"time"
+)
+
+const (
+	FactorEdbSeriesChartCalculateTypeCorrelation = 1 // 相关性计算
+)
+
+// FactorEdbSeriesChartMapping 因子指标系列-图表关联
+type FactorEdbSeriesChartMapping struct {
+	FactorEdbSeriesChartMappingId int       `orm:"column(factor_edb_series_chart_mapping_id);pk"`
+	ChartInfoId                   int       `description:"图表ID"`
+	Source                        int       `description:"图表来源, 同chart_info表source"`
+	CalculateType                 int       `description:"计算方式: 1-相关性"`
+	CalculatePars                 string    `description:"计算参数-JSON(如计算窗口等)"`
+	CalculateData                 string    `description:"计算数据-JSON(如相关性矩阵等)"`
+	FactorEdbSeriesId             int       `description:"因子指标系列ID"`
+	EdbInfoId                     int       `description:"指标ID"`
+	EdbUsed                       int       `description:"指标是否使用: 0-否; 1-是"`
+	CreateTime                    time.Time `description:"创建时间"`
+	ModifyTime                    time.Time `description:"修改时间"`
+}
+
+func (m *FactorEdbSeriesChartMapping) TableName() string {
+	return "factor_edb_series_chart_mapping"
+}
+
+type MultipleFactorSeriesChartMappingCols struct {
+	PrimaryId         string
+	ChartInfoId       string
+	Source            string
+	CalculateType     string
+	CalculatePars     string
+	CalculateData     string
+	FactorEdbSeriesId string
+	EdbInfoId         string
+	EdbUsed           string
+	CreateTime        string
+	ModifyTime        string
+}
+
+func (m *FactorEdbSeriesChartMapping) Cols() MultipleFactorSeriesChartMappingCols {
+	return MultipleFactorSeriesChartMappingCols{
+		PrimaryId:         "factor_edb_series_chart_mapping_id",
+		ChartInfoId:       "chart_info_id",
+		Source:            "source",
+		CalculateType:     "calculate_type",
+		CalculatePars:     "calculate_pars",
+		CalculateData:     "calculate_data",
+		FactorEdbSeriesId: "factor_edb_series_id",
+		EdbInfoId:         "edb_info_id",
+		EdbUsed:           "edb_used",
+		CreateTime:        "create_time",
+		ModifyTime:        "modify_time",
+	}
+}
+
+func (m *FactorEdbSeriesChartMapping) Create() (err error) {
+	o := orm.NewOrm()
+	id, err := o.Insert(m)
+	if err != nil {
+		return
+	}
+	m.FactorEdbSeriesChartMappingId = int(id)
+	return
+}
+
+func (m *FactorEdbSeriesChartMapping) CreateMulti(items []*FactorEdbSeriesChartMapping) (err error) {
+	if len(items) == 0 {
+		return
+	}
+	o := orm.NewOrm()
+	_, err = o.InsertMulti(len(items), items)
+	return
+}
+
+func (m *FactorEdbSeriesChartMapping) Update(cols []string) (err error) {
+	o := orm.NewOrm()
+	_, err = o.Update(m, cols...)
+	return
+}
+
+func (m *FactorEdbSeriesChartMapping) Remove() (err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.Cols().PrimaryId)
+	_, err = o.Raw(sql, m.FactorEdbSeriesChartMappingId).Exec()
+	return
+}
+
+func (m *FactorEdbSeriesChartMapping) MultiRemove(ids []int) (err error) {
+	if len(ids) == 0 {
+		return
+	}
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s IN (%s)`, m.TableName(), m.Cols().PrimaryId, utils.GetOrmInReplace(len(ids)))
+	_, err = o.Raw(sql, ids).Exec()
+	return
+}
+
+func (m *FactorEdbSeriesChartMapping) GetItemById(id int) (item *FactorEdbSeriesChartMapping, err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.Cols().PrimaryId)
+	err = o.Raw(sql, id).QueryRow(&item)
+	return
+}
+
+func (m *FactorEdbSeriesChartMapping) GetItemByCondition(condition string, pars []interface{}, orderRule string) (item *FactorEdbSeriesChartMapping, err error) {
+	o := orm.NewOrm()
+	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 *FactorEdbSeriesChartMapping) GetCountByCondition(condition string, pars []interface{}) (count int, err error) {
+	o := orm.NewOrm()
+	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 *FactorEdbSeriesChartMapping) GetItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string) (items []*FactorEdbSeriesChartMapping, err error) {
+	o := orm.NewOrm()
+	fields := strings.Join(fieldArr, ",")
+	if len(fieldArr) == 0 {
+		fields = `*`
+	}
+	order := fmt.Sprintf(`ORDER BY %s DESC`, m.Cols().CreateTime)
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT %s FROM %s WHERE 1=1 %s %s`, fields, m.TableName(), condition, order)
+	_, err = o.Raw(sql, pars).QueryRows(&items)
+	return
+}
+
+func (m *FactorEdbSeriesChartMapping) GetPageItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string, startSize, pageSize int) (items []*FactorEdbSeriesChartMapping, err error) {
+	o := orm.NewOrm()
+	fields := strings.Join(fieldArr, ",")
+	if len(fieldArr) == 0 {
+		fields = `*`
+	}
+	order := fmt.Sprintf(`ORDER BY %s DESC`, m.Cols().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
+}
+
+// GetDistinctSeriesIdByChartId 获取图表关联的系列ID
+func (m *FactorEdbSeriesChartMapping) GetDistinctSeriesIdByChartId(chartId int) (seriesIds []int, err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`SELECT DISTINCT %s FROM %s WHERE %s = ?`, m.Cols().FactorEdbSeriesId, m.TableName(), m.Cols().ChartInfoId)
+	_, err = o.Raw(sql, chartId).QueryRows(&seriesIds)
+	return
+}
+
+// FactorEdbSeriesChartCalculateCorrelationReq 图表相关性计算参数
+type FactorEdbSeriesChartCalculateCorrelationReq struct {
+	BaseEdbInfoId  int    `description:"标的指标ID"`
+	LeadValue      int    `description:"领先期数"`
+	LeadUnit       string `description:"频度"`
+	CalculateValue int    `description:"计算窗口"`
+	CalculateUnit  string `description:"计算频度"`
+}

+ 167 - 0
models/data_manage/factor_edb_series_mapping.go

@@ -0,0 +1,167 @@
+package data_manage
+
+import (
+	"eta/eta_task/utils"
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
+	"strings"
+	"time"
+)
+
+// FactorEdbSeriesMapping 因子指标系列-指标关联表
+type FactorEdbSeriesMapping struct {
+	FactorEdbSeriesMappingId int       `orm:"column(factor_edb_series_mapping_id);pk"`
+	FactorEdbSeriesId        int       `description:"因子指标系列ID"`
+	EdbInfoId                int       `description:"指标ID"`
+	EdbCode                  string    `description:"指标编码"`
+	CreateTime               time.Time `description:"创建时间"`
+	ModifyTime               time.Time `description:"修改时间"`
+}
+
+func (m *FactorEdbSeriesMapping) TableName() string {
+	return "factor_edb_series_mapping"
+}
+
+type FactorEdbSeriesMappingCols struct {
+	PrimaryId         string
+	FactorEdbSeriesId string
+	EdbInfoId         string
+	EdbCode           string
+	CreateTime        string
+	ModifyTime        string
+}
+
+func (m *FactorEdbSeriesMapping) Cols() FactorEdbSeriesMappingCols {
+	return FactorEdbSeriesMappingCols{
+		PrimaryId:         "factor_edb_series_mapping_id",
+		FactorEdbSeriesId: "factor_edb_series_id",
+		EdbInfoId:         "edb_info_id",
+		EdbCode:           "edb_code",
+		CreateTime:        "create_time",
+		ModifyTime:        "modify_time",
+	}
+}
+
+func (m *FactorEdbSeriesMapping) Create() (err error) {
+	o := orm.NewOrm()
+	id, err := o.Insert(m)
+	if err != nil {
+		return
+	}
+	m.FactorEdbSeriesMappingId = int(id)
+	return
+}
+
+func (m *FactorEdbSeriesMapping) CreateMulti(items []*FactorEdbSeriesMapping) (err error) {
+	if len(items) == 0 {
+		return
+	}
+	o := orm.NewOrm()
+	_, err = o.InsertMulti(len(items), items)
+	return
+}
+
+func (m *FactorEdbSeriesMapping) Update(cols []string) (err error) {
+	o := orm.NewOrm()
+	_, err = o.Update(m, cols...)
+	return
+}
+
+func (m *FactorEdbSeriesMapping) Remove() (err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.Cols().PrimaryId)
+	_, err = o.Raw(sql, m.FactorEdbSeriesMappingId).Exec()
+	return
+}
+
+func (m *FactorEdbSeriesMapping) MultiRemove(ids []int) (err error) {
+	if len(ids) == 0 {
+		return
+	}
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s IN (%s)`, m.TableName(), m.Cols().PrimaryId, utils.GetOrmInReplace(len(ids)))
+	_, err = o.Raw(sql, ids).Exec()
+	return
+}
+
+func (m *FactorEdbSeriesMapping) RemoveByCondition(condition string, pars []interface{}) (err error) {
+	if condition == "" {
+		return
+	}
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s`, m.TableName(), condition)
+	_, err = o.Raw(sql, pars).Exec()
+	return
+}
+
+func (m *FactorEdbSeriesMapping) GetItemById(id int) (item *FactorEdbSeriesMapping, err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.Cols().PrimaryId)
+	err = o.Raw(sql, id).QueryRow(&item)
+	return
+}
+
+func (m *FactorEdbSeriesMapping) GetItemByCondition(condition string, pars []interface{}, orderRule string) (item *FactorEdbSeriesMapping, err error) {
+	o := orm.NewOrm()
+	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 *FactorEdbSeriesMapping) GetCountByCondition(condition string, pars []interface{}) (count int, err error) {
+	o := orm.NewOrm()
+	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 *FactorEdbSeriesMapping) GetItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string) (items []*FactorEdbSeriesMapping, err error) {
+	o := orm.NewOrm()
+	fields := strings.Join(fieldArr, ",")
+	if len(fieldArr) == 0 {
+		fields = `*`
+	}
+	order := fmt.Sprintf(`ORDER BY %s DESC`, m.Cols().CreateTime)
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT %s FROM %s WHERE 1=1 %s %s`, fields, m.TableName(), condition, order)
+	_, err = o.Raw(sql, pars).QueryRows(&items)
+	return
+}
+
+func (m *FactorEdbSeriesMapping) GetPageItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string, startSize, pageSize int) (items []*FactorEdbSeriesMapping, err error) {
+	o := orm.NewOrm()
+	fields := strings.Join(fieldArr, ",")
+	if len(fieldArr) == 0 {
+		fields = `*`
+	}
+	order := fmt.Sprintf(`ORDER BY %s DESC`, m.Cols().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
+}
+
+// FactorEdbSeriesMappingItem 因子指标系列-指标关联信息
+type FactorEdbSeriesMappingItem struct {
+	SeriesId  int    `description:"因子指标系列ID"`
+	EdbInfoId int    `description:"指标ID"`
+	EdbCode   string `description:"指标编码"`
+	EdbName   string `description:"指标名称"`
+	EdbNameEn string `description:"指标名称-英文"`
+}
+
+func (m *FactorEdbSeriesMapping) Format2Item() (item *FactorEdbSeriesMappingItem) {
+	item = new(FactorEdbSeriesMappingItem)
+	item.SeriesId = m.FactorEdbSeriesId
+	item.EdbInfoId = m.EdbInfoId
+	item.EdbCode = m.EdbCode
+	return
+}

+ 15 - 0
models/db.go

@@ -4,6 +4,7 @@ import (
 	"eta/eta_task/models/data_manage"
 	"eta/eta_task/models/data_manage/edb_refresh"
 	"eta/eta_task/models/data_manage/future_good"
+	"eta/eta_task/models/report"
 	"eta/eta_task/utils"
 	_ "github.com/go-sql-driver/mysql"
 	"time"
@@ -78,6 +79,9 @@ func init() {
 	//注册持仓分析 数据表
 	initTradePositionTop()
 
+	// 研报数据表
+	initReport()
+
 	// 智能研报数据表
 	initSmartReport()
 
@@ -127,6 +131,8 @@ func initEdbDataTable() {
 		new(data_manage.BaseFromIcpiClassify),
 		new(data_manage.BaseFromIcpiData),
 		new(data_manage.BusinessSysInteractionLog), // 商家系统交互记录表
+
+		new(data_manage.EdbInfoRelation), //指标引用关联表
 	)
 }
 
@@ -152,6 +158,15 @@ func initTradePositionTop() {
 	)
 }
 
+// initReport 注册研报数据表
+func initReport() {
+	orm.RegisterModel(
+		new(Report),
+		new(ReportChapter),
+		new(report.ReportChapterPermissionMapping), // 报告章节的权限关系表
+	)
+}
+
 // initSmartReport 注册智能研报数据表
 func initSmartReport() {
 	orm.RegisterModel(

+ 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
+}

+ 48 - 45
models/report.go

@@ -35,6 +35,8 @@ type Report struct {
 	PreMsgSend         int       `description:"定时发布成功后是否立即推送模版消息:0否,1是"`
 	AdminId            int
 	AdminName          string `description:"系统用户名称"`
+	ClassifyIdThird    int    `description:"三级分类id"`
+	ClassifyNameThird  string `description:"三级分类名称"`
 }
 
 func GetReportById(reportId int) (item *ReportDetail, err error) {
@@ -137,46 +139,6 @@ func ModifyReportVideo(reportId int, videoUrl, videoName, videoSize string, play
 	return
 }
 
-// ReportChapter 报告章节
-type ReportChapter struct {
-	ReportChapterId   int       `orm:"column(report_chapter_id);pk" description:"报告章节ID"`
-	ReportId          int       `description:"报告ID"`
-	ReportType        string    `description:"报告类型 day-晨报 week-周报"`
-	ClassifyIdFirst   int       `description:"一级分类id"`
-	ClassifyNameFirst string    `description:"一级分类名称"`
-	TypeId            int       `description:"品种ID"`
-	TypeName          string    `description:"品种名称"`
-	Title             string    `description:"标题"`
-	Abstract          string    `description:"摘要"`
-	AddType           int       `description:"新增方式:1:新增报告,2:继承报告"`
-	Author            string    `description:"作者"`
-	Content           string    `description:"内容"`
-	ContentSub        string    `description:"内容前两个章节"`
-	Stage             int       `description:"期数"`
-	Trend             string    `description:"趋势观点"`
-	Sort              int       `description:"排序: 数值越小越靠前"`
-	IsEdit            int       `description:"是否已编辑 0-待编辑 1-已编辑"`
-	PublishState      int       `description:"发布状态 1-待发布,2-已发布"`
-	PublishTime       time.Time `description:"发布时间"`
-	VideoUrl          string    `description:"音频文件URL"`
-	VideoName         string    `description:"音频文件名称"`
-	VideoPlaySeconds  string    `description:"音频播放时长"`
-	VideoSize         string    `description:"音频文件大小,单位M"`
-	VideoKind         int       `description:"音频生成方式:1,手动上传,2:自动生成"`
-	CreateTime        string    `description:"创建时间"`
-	ModifyTime        time.Time `description:"修改时间"`
-	OriginalVideoUrl  string    `description:"原始音频文件URL"`
-}
-
-// GetPublishedChapterListByReportId 根据ReportId获取已发布章节列表
-func GetPublishedChapterListByReportId(reportId int) (list []*ReportChapter, err error) {
-	o := orm.NewOrmUsingDB("rddp")
-	sql := ` SELECT * FROM report_chapter WHERE report_id = ? AND publish_state = 2 ORDER BY sort ASC`
-	_, err = o.Raw(sql, reportId).QueryRows(&list)
-
-	return
-}
-
 type ReportChapterTypePermission struct {
 	Id                    int       `orm:"column(id);pk" description:"主键ID"`
 	ReportChapterTypeId   int       `description:"报告章节类型ID"`
@@ -208,6 +170,8 @@ type ElasticReportDetail struct {
 	ClassifyNameFirst  string `description:"一级分类名称"`
 	ClassifyIdSecond   int    `description:"二级分类ID"`
 	ClassifyNameSecond string `description:"二级分类名称"`
+	ClassifyId         int    `description:"最小单元的分类ID"`
+	ClassifyName       string `description:"最小单元的分类名称"`
 	Categories         string `description:"关联的品种名称(包括品种别名)"`
 	StageStr           string `description:"报告期数"`
 }
@@ -217,11 +181,10 @@ type ChartPermissionMappingIdName struct {
 	PermissionName string
 }
 
-func GetChartPermissionNameFromMappingByKeyword(keyword string, source string) (list []*ChartPermissionMappingIdName, err error) {
-	o := orm.NewOrm()
-	sql := " SELECT b.chart_permission_id AS permission_id,b.permission_name FROM chart_permission_search_key_word_mapping AS a INNER JOIN chart_permission AS b ON a.chart_permission_id = b.chart_permission_id WHERE a.`from` = ? AND a.key_word = ? "
-	_, err = o.Raw(sql, source, keyword).QueryRows(&list)
-
+func GetChartPermissionNameFromMappingByKeyword(source string, classifyId int) (list []*ChartPermissionMappingIdName, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := " SELECT b.chart_permission_id AS permission_id,b.permission_name FROM chart_permission_search_key_word_mapping AS a INNER JOIN chart_permission AS b ON a.chart_permission_id = b.chart_permission_id WHERE a.`from` = ? AND a.classify_id = ? "
+	_, err = o.Raw(sql, source, classifyId).QueryRows(&list)
 	return
 }
 
@@ -265,3 +228,43 @@ func ClearReportSaveLog(date string) (err error) {
 	_, err = o.Raw(sql, date).Exec()
 	return
 }
+
+// PublishReportAndChapter 发布报告及章节
+func PublishReportAndChapter(reportInfo *Report, isPublishReport bool, cols []string) (err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	to, err := o.Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = to.Rollback()
+		} else {
+			_ = to.Commit()
+		}
+	}()
+	// 更新报告
+	if isPublishReport {
+		_, err = to.Update(reportInfo, cols...)
+		if err != nil {
+			return
+		}
+	}
+
+	// 发布该报告的所有章节
+	sql := ` UPDATE report_chapter SET publish_state = 2, publish_time = ? WHERE report_id = ?  `
+	_, err = to.Raw(sql, reportInfo.PublishTime, reportInfo.Id).Exec()
+
+	// 发布章节
+	//if len(publishIds) > 0 {
+	//	sql := ` UPDATE report_chapter SET publish_state = 2, publish_time = ? WHERE report_id = ? AND report_chapter_id IN (` + utils.GetOrmInReplace(len(publishIds)) + `) `
+	//	_, err = to.Raw(sql, reportInfo.PublishTime, reportInfo.Id, publishIds).Exec()
+	//}
+
+	//if len(unPublishIds) > 0 {
+	//	sql := ` UPDATE report_chapter SET publish_state = 1, publish_time = NULL, is_edit = 0 WHERE report_id = ? AND report_chapter_id IN (` + utils.GetOrmInReplace(len(unPublishIds)) + `) `
+	//	_, err = to.Raw(sql, reportInfo.Id, unPublishIds).Exec()
+	//}
+
+	return
+}

+ 152 - 0
models/report/report_chapter_permission_mapping.go

@@ -0,0 +1,152 @@
+package report
+
+import (
+	"eta/eta_task/utils"
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+// ReportChapterPermissionMapping
+// @Description: 报告章节的权限关系表
+type ReportChapterPermissionMapping struct {
+	ReportChapterPermissionMappingId int `orm:"column(report_chapter_permission_mapping_id)"`
+	ReportChapterId                  int `description:"报告章节的id"` // 报告章节的id
+	ChartPermissionId                int `description:"权限id"`    // 权限id
+	CreateTime                       time.Time
+}
+
+// MultiAddReportChapterPermissionMappingPermission
+// @Description: 批量添加报告品种权限用户
+// @author: Roc
+// @receiver m
+// @datetime 2024-06-04 15:36:02
+// @param reportChapterId int
+// @param list []*ReportChapterPermissionMapping
+// @return err error
+func (m ReportChapterPermissionMapping) MultiAddReportChapterPermissionMappingPermission(reportChapterId int, list []*ReportChapterPermissionMapping) (err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	to, err := o.Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = to.Rollback()
+		} else {
+			_ = to.Commit()
+		}
+	}()
+
+	sql := "DELETE from report_chapter_permission_mapping where report_chapter_id=?"
+	_, err = to.Raw(sql, reportChapterId).Exec()
+	if err != nil {
+		return
+	}
+
+	// 新增品种权限记录
+	if len(list) > 0 {
+		_, tmpErr := to.InsertMulti(500, list)
+		if tmpErr != nil {
+			err = tmpErr
+			return
+		}
+	}
+
+	return
+}
+
+// GetPermissionListById
+// @Description: 根据id获取品种权限列表
+// @author: Roc
+// @receiver m
+// @datetime 2024-06-04 15:33:58
+// @param reportChapterId int
+// @return list []*ReportChapterPermissionMapping
+// @return err error
+func (m ReportChapterPermissionMapping) GetPermissionListById(reportChapterId int) (list []*ReportChapterPermissionMapping, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := `SELECT * FROM report_chapter_permission_mapping WHERE report_chapter_id=? `
+	_, err = o.Raw(sql, reportChapterId).QueryRows(&list)
+
+	return
+}
+
+// ReportChapterPermissionItem
+// @Description: 报告章节的权限关系表(带有品种名称)
+type ReportChapterPermissionItem struct {
+	ReportChapterPermissionMappingId int    `orm:"column(report_chapter_permission_mapping_id)"`
+	ReportChapterId                  int    `description:"报告章节的id"`
+	ChartPermissionId                int    `description:"权限id"`
+	ChartPermissionName              string `description:"品种名称"`
+	CreateTime                       time.Time
+}
+
+// GetPermissionItemListById
+// @Description: 根据id获取品种权限列表(带有品种名称)
+// @author: Roc
+// @receiver m
+// @datetime 2024-06-04 15:33:58
+// @param reportChapterId int
+// @return list []*ReportChapterPermissionMapping
+// @return err error
+func (m ReportChapterPermissionMapping) GetPermissionItemListById(reportChapterId int) (list []*ReportChapterPermissionItem, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := `SELECT a.*,b.chart_permission_name FROM report_chapter_permission_mapping AS a 
+         JOIN chart_permission AS b on a.chart_permission_id=b.chart_permission_id WHERE report_chapter_id=? `
+	_, err = o.Raw(sql, reportChapterId).QueryRows(&list)
+
+	return
+}
+
+// GetPermissionListByIdList
+// @Description: 根据id列表获取品种权限列表
+// @author: Roc
+// @receiver m
+// @datetime 2024-06-04 15:33:58
+// @param reportChapterIdList []int
+// @return list []*ReportChapterPermissionMapping
+// @return err error
+func (m ReportChapterPermissionMapping) GetPermissionListByIdList(reportChapterIdList []int) (list []*ReportChapterPermissionMapping, err error) {
+	num := len(reportChapterIdList)
+	if num <= 0 {
+		return
+	}
+
+	o := orm.NewOrmUsingDB("rddp")
+	sql := `SELECT * FROM report_chapter_permission_mapping WHERE report_chapter_id in (` + utils.GetOrmInReplace(num) + `) `
+	_, err = o.Raw(sql, reportChapterIdList).QueryRows(&list)
+
+	return
+}
+
+// MultiAdd
+// @Description: 批量添加
+// @author: Roc
+// @receiver m
+// @datetime 2024-06-20 18:04:33
+// @param list []*ReportChapterPermissionMapping
+// @return err error
+func (m ReportChapterPermissionMapping) MultiAdd(list []*ReportChapterPermissionMapping) (err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	to, err := o.Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = to.Rollback()
+		} else {
+			_ = to.Commit()
+		}
+	}()
+
+	// 新增品种权限记录
+	if len(list) > 0 {
+		_, err = to.InsertMulti(500, list)
+		if err != nil {
+			return
+		}
+	}
+
+	return
+}

+ 75 - 0
models/report_chapter.go

@@ -0,0 +1,75 @@
+package models
+
+import (
+	"eta/eta_task/utils"
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+// ReportChapter 报告章节
+type ReportChapter struct {
+	ReportChapterId   int       `orm:"column(report_chapter_id);pk" description:"报告章节ID"`
+	ReportId          int       `description:"报告ID"`
+	ReportType        string    `description:"报告类型 day-晨报 week-周报"`
+	ClassifyIdFirst   int       `description:"一级分类id"`
+	ClassifyNameFirst string    `description:"一级分类名称"`
+	TypeId            int       `description:"品种ID"`
+	TypeName          string    `description:"品种名称"`
+	Title             string    `description:"标题"`
+	Abstract          string    `description:"摘要"`
+	AddType           int       `description:"新增方式:1:新增报告,2:继承报告"`
+	Author            string    `description:"作者"`
+	Content           string    `description:"内容"`
+	ContentSub        string    `description:"内容前两个章节"`
+	Stage             int       `description:"期数"`
+	Trend             string    `description:"趋势观点"`
+	Sort              int       `description:"排序: 数值越小越靠前"`
+	IsEdit            int       `description:"是否已编辑 0-待编辑 1-已编辑"`
+	PublishState      int       `description:"发布状态 1-待发布,2-已发布"`
+	PublishTime       time.Time `description:"发布时间"`
+	VideoUrl          string    `description:"音频文件URL"`
+	VideoName         string    `description:"音频文件名称"`
+	VideoPlaySeconds  string    `description:"音频播放时长"`
+	VideoSize         string    `description:"音频文件大小,单位M"`
+	VideoKind         int       `description:"音频生成方式:1,手动上传,2:自动生成"`
+	CreateTime        string    `description:"创建时间"`
+	ModifyTime        time.Time `description:"修改时间"`
+	OriginalVideoUrl  string    `description:"原始音频文件URL"`
+}
+
+// GetPublishedChapterListByReportId 根据ReportId获取已发布章节列表
+func GetPublishedChapterListByReportId(reportId int) (list []*ReportChapter, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := ` SELECT * FROM report_chapter WHERE report_id = ? AND publish_state = 2 ORDER BY sort ASC`
+	_, err = o.Raw(sql, reportId).QueryRows(&list)
+
+	return
+}
+
+// GetChapterListByReportId 根据ReportId获取章节列表
+func GetChapterListByReportId(reportId int) (list []*ReportChapter, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := ` SELECT * FROM report_chapter WHERE report_id = ? ORDER BY sort ASC`
+	_, err = o.Raw(sql, reportId).QueryRows(&list)
+
+	return
+}
+
+// GetChapterListByChapterIds 根据ReportId获取章节列表
+func GetChapterListByChapterIds(chapterIds []int) (list []*ReportChapter, err error) {
+	if len(chapterIds) == 0 {
+		return
+	}
+	o := orm.NewOrmUsingDB("rddp")
+	sql := ` SELECT * FROM report_chapter WHERE report_chapter_id IN (` + utils.GetOrmInReplace(len(chapterIds)) + `) ORDER BY sort ASC`
+	_, err = o.Raw(sql, chapterIds).QueryRows(&list)
+	return
+}
+
+// UpdateChapter 更新报表章节
+func (chapterChapterInfo *ReportChapter) UpdateChapter(cols []string) (err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	_, err = o.Update(chapterChapterInfo, cols...)
+
+	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"`
+}

+ 24 - 0
models/wx_template_msg.go

@@ -63,3 +63,27 @@ func GetOpenIdArrByClassifyNameSecond(classifyNameSecond string) (items []string
 	_, err = o.Raw(sql, classifyNameSecond).QueryRows(&items)
 	return
 }
+
+// GetOpenIdArrByClassifyId
+// @Description: 根据分类id获取关联的用户微信openid
+// @author: Roc
+// @datetime 2024-06-28 14:57:27
+// @param classifyId int
+// @return items []string
+// @return err error
+func GetOpenIdArrByClassifyId(classifyId int) (items []string, err error) {
+	sql := ` SELECT DISTINCT ur.open_id FROM wx_user AS wu 
+			INNER JOIN company AS c ON c.company_id = wu.company_id 
+			INNER JOIN company_product AS d ON c.company_id=d.company_id
+			INNER JOIN user_record  AS ur ON wu.user_id=ur.user_id
+			INNER JOIN company_report_permission AS e ON d.company_id=e.company_id
+			INNER JOIN chart_permission AS f ON e.chart_permission_id=f.chart_permission_id
+			INNER JOIN chart_permission_search_key_word_mapping AS g ON f.chart_permission_id=g.chart_permission_id
+			WHERE ur.open_id != "" AND ur.subscribe=1 AND ur.create_platform=1 AND  d.status IN('正式','试用','永续') AND  e.status IN('正式','试用','永续') 
+			AND g.from='rddp'
+			AND g.classify_id=?
+			ORDER BY FIELD(c.company_id, 16) DESC, ur.user_record_id ASC  `
+	o := orm.NewOrmUsingDB("weekly")
+	_, err = o.Raw(sql, classifyId).QueryRows(&items)
+	return
+}

+ 19 - 0
routers/commentsRouter.go

@@ -0,0 +1,19 @@
+package routers
+
+import (
+	beego "github.com/beego/beego/v2/server/web"
+	"github.com/beego/beego/v2/server/web/context/param"
+)
+
+func init() {
+
+    beego.GlobalControllerRouter["eta/eta_task/controllers:DataInitController"] = append(beego.GlobalControllerRouter["eta/eta_task/controllers:DataInitController"],
+        beego.ControllerComments{
+            Method: "InitEdbRelation",
+            Router: `/relation_init`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+}

+ 13 - 1
routers/router.go

@@ -7,7 +7,19 @@
 // @LicenseUrl http://www.apache.org/licenses/LICENSE-2.0.html
 package routers
 
+import (
+	"eta/eta_task/controllers"
+	"github.com/beego/beego/v2/server/web"
+)
 
 func init() {
-
+	//解决跨域问题
+	ns := web.NewNamespace("/v1",
+		web.NSNamespace("/data",
+			web.NSInclude(
+				&controllers.DataInitController{},
+			),
+		),
+	)
+	web.AddNamespace(ns)
 }

+ 2 - 2
services/data/edb_info.go

@@ -251,7 +251,7 @@ func RefreshDataFromCalculateAll() (err error) {
 	var condition string
 	var pars []interface{}
 	// 查询 普通指标的计算指标
-	condition += " AND edb_type=?  AND edb_info_type=? "
+	condition += " AND edb_type=?  AND edb_info_type=? AND no_update=0"
 	pars = append(pars, 2, 0)
 
 	items, err := data_manage.GetEdbInfoByCondition(condition, pars, 0)
@@ -912,7 +912,7 @@ func RefreshDataFromMysteelChemical(wg *sync.WaitGroup) (err error) {
 	}()
 	var condition string
 	var pars []interface{}
-	condition += " AND source=? "
+	condition += " AND source=? AND no_update = 0 "
 	pars = append(pars, utils.DATA_SOURCE_MYSTEEL_CHEMICAL)
 	items, err := data_manage.GetEdbInfoByCondition(condition, pars, 0)
 	if err != nil {

+ 117 - 0
services/data/factor_edb_series.go

@@ -0,0 +1,117 @@
+package data
+
+import (
+	"encoding/json"
+	"eta/eta_task/models"
+	"eta/eta_task/models/data_manage"
+	"eta/eta_task/services/alarm_msg"
+	"eta/eta_task/utils"
+	"fmt"
+)
+
+// RefreshFactorEdbCalculateData 刷新因子指标计算数据
+func RefreshFactorEdbCalculateData() (err error) {
+	defer func() {
+		if err != nil {
+			tips := fmt.Sprintf("RefreshFactorEdbCalculateData ErrMsg: %v", err)
+			utils.FileLog.Info(tips)
+			go alarm_msg.SendAlarmMsg(tips, 3)
+		}
+	}()
+
+	mappingOb := new(data_manage.FactorEdbSeriesMapping)
+	list, e := mappingOb.GetItemsByCondition(``, make([]interface{}, 0), []string{fmt.Sprintf("DISTINCT %s", mappingOb.Cols().EdbInfoId), mappingOb.Cols().EdbCode}, "")
+	if e != nil {
+		err = fmt.Errorf("获取系列因子指标失败, err: %v", e)
+		return
+	}
+	if len(list) == 0 {
+		return
+	}
+
+	for _, v := range list {
+		_, e = PostRefreshFactorEdbRecalculate(v.EdbInfoId, v.EdbCode)
+		if e != nil {
+			utils.FileLog.Info(fmt.Sprintf("PostRefreshFactorEdbRecalculate err, EdbInfoId: %d, err: %v", v.EdbInfoId, e))
+			continue
+		}
+	}
+	return
+}
+
+// RefreshFactorEdbChartCalculateData 刷新因子指标图表计算数据
+func RefreshFactorEdbChartCalculateData() (err error) {
+	defer func() {
+		if err != nil {
+			tips := fmt.Sprintf("RefreshFactorEdbChartCalculateData ErrMsg: %v", err)
+			utils.FileLog.Info(tips)
+			go alarm_msg.SendAlarmMsg(tips, 3)
+		}
+	}()
+
+	mappingOb := new(data_manage.FactorEdbSeriesChartMapping)
+	list, e := mappingOb.GetItemsByCondition(``, make([]interface{}, 0), []string{fmt.Sprintf("DISTINCT %s", mappingOb.Cols().ChartInfoId)}, "")
+	if e != nil {
+		err = fmt.Errorf("获取指标系列关联图表失败, err: %v", e)
+		return
+	}
+	if len(list) == 0 {
+		return
+	}
+
+	for _, v := range list {
+		_, e = PostRefreshFactorEdbChartRecalculate(v.ChartInfoId)
+		if e != nil {
+			utils.FileLog.Info(fmt.Sprintf("PostRefreshFactorEdbChartRecalculate err, ChartInfoId: %d, err: %v", v.ChartInfoId, e))
+			continue
+		}
+	}
+	return
+}
+
+// PostRefreshFactorEdbRecalculate 因子指标重计算
+func PostRefreshFactorEdbRecalculate(edbInfoId int, edbCode string) (resp *models.BaseResponse, err error) {
+	param := make(map[string]interface{})
+	param["EdbInfoId"] = edbInfoId
+	param["EdbCode"] = edbCode
+	postUrl := fmt.Sprintf("%s%s", utils.EDB_LIB_URL, "factor_edb_series/recalculate")
+	postData, e := json.Marshal(param)
+	if e != nil {
+		err = fmt.Errorf("param json err: %v", e)
+		return
+	}
+	result, e := HttpPost(postUrl, string(postData), "application/json")
+	if e != nil {
+		err = fmt.Errorf("http post err: %v", e)
+		return
+	}
+	utils.FileLog.Info("PostRefreshFactorEdbRecalculate:" + postUrl + ";" + string(postData) + ";result:" + string(result))
+	if e = json.Unmarshal(result, &resp); e != nil {
+		err = fmt.Errorf("resp unmarshal err: %v", e)
+		return
+	}
+	return
+}
+
+// PostRefreshFactorEdbChartRecalculate 因子指标图表重计算
+func PostRefreshFactorEdbChartRecalculate(chartInfoId int) (resp *models.BaseResponse, err error) {
+	param := make(map[string]interface{})
+	param["ChartInfoId"] = chartInfoId
+	postUrl := fmt.Sprintf("%s%s", utils.EDB_LIB_URL, "factor_edb_series/chart_recalculate")
+	postData, e := json.Marshal(param)
+	if e != nil {
+		err = fmt.Errorf("param json err: %v", e)
+		return
+	}
+	result, e := HttpPost(postUrl, string(postData), "application/json")
+	if e != nil {
+		err = fmt.Errorf("http post err: %v", e)
+		return
+	}
+	utils.FileLog.Info("PostRefreshFactorEdbChartRecalculate:" + postUrl + ";" + string(postData) + ";result:" + string(result))
+	if e = json.Unmarshal(result, &resp); e != nil {
+		err = fmt.Errorf("resp unmarshal err: %v", e)
+		return
+	}
+	return
+}

+ 211 - 0
services/edb_refresh.go

@@ -2,6 +2,7 @@ package services
 
 import (
 	"context"
+	"encoding/json"
 	"eta/eta_task/models"
 	"eta/eta_task/models/data_manage"
 	"eta/eta_task/models/data_manage/edb_refresh"
@@ -665,3 +666,213 @@ 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)
+		fromEdbIdList := make([]int, 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)
+			fromEdbIdList = 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 item.EdbInfoType == 0 && item.EdbType == 1 {
+						fromEdbIdList = append(fromEdbIdList, item.EdbInfoId)
+					}
+					// 更新指标禁止刷新状态
+					if len(stopRefreshIds) > 100 {
+						// 查询相关的计算指标
+						calculateEdbIdList := make([]int, 0)
+						if len(fromEdbIdList) > 0 {
+							hasFind := make(map[int]struct{})
+							calculateEdbIdList, err = GetCalculateEdbByFromEdbInfo(fromEdbIdList, calculateEdbIdList, hasFind)
+							if err != nil {
+								err = fmt.Errorf("查询计算指标信息失败:%v", err)
+								return
+							}
+						}
+						err = data_manage.ModifyEdbUpdateStatus(stopRefreshIds, stopRefreshMysteelCode, calculateEdbIdList)
+						if err != nil {
+							err = fmt.Errorf("更新指标禁止刷新状态失败:%v", err)
+							return
+						}
+						stopRefreshIds = []int{}
+						stopRefreshMysteelCode = []string{}
+					}
+				}
+			}
+		}
+
+		// 更新指标禁止刷新状态
+		if len(stopRefreshIds) > 0 {
+			// 查询相关的计算指标
+			calculateEdbIdList := make([]int, 0)
+			if len(fromEdbIdList) > 0 {
+				hasFind := make(map[int]struct{})
+				calculateEdbIdList, err = GetCalculateEdbByFromEdbInfo(fromEdbIdList, calculateEdbIdList, hasFind)
+				if err != nil {
+					err = fmt.Errorf("查询计算指标信息失败:%v", err)
+					return
+				}
+			}
+			err = data_manage.ModifyEdbUpdateStatus(stopRefreshIds, stopRefreshMysteelCode, calculateEdbIdList)
+			if err != nil {
+				err = fmt.Errorf("更新指标禁止刷新状态失败:%v", err)
+				return
+			}
+		}
+	}
+	return
+}

+ 1202 - 0
services/edb_relation.go

@@ -0,0 +1,1202 @@
+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 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
+				}
+				if chartInfo.Source == utils.CHART_SOURCE_CROSS_HEDGING { //过滤掉跨品种分析的图表
+					continue
+				}
+				edbInfo, ok2 := edbInfoMap[v.EdbInfoId]
+				if !ok2 {
+					continue
+				}
+				// 去掉预测指标
+				if edbInfo.EdbInfoType == 1 {
+					continue
+				}
+
+				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 == 0 {
+					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)
+		chartIdMap := make(map[int]struct{})
+		tagIds := make([]int, 0)
+		tagIdsMap := make(map[int]struct{})
+		tagChartMap := make(map[int][]*cross_variety.ChartInfoCrossVariety)
+		for _, v := range list {
+			if _, ok := chartIdMap[v.ChartInfoId]; !ok {
+				chartIdMap[v.ChartInfoId] = struct{}{}
+				chartIds = append(chartIds, v.ChartInfoId)
+			}
+			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
+			}
+		}
+		chartInfoMap := make(map[int]*data_manage.ChartInfo)
+		if len(chartIds) > 0 {
+			// 查询图表信息
+			chartInfoList, e := data_manage.GetChartInfoByChartInfoIds(chartIds)
+			if e != nil {
+				err = fmt.Errorf("查询图表信息列表失败 Err:%s", e)
+				return
+			}
+			for _, v := range chartInfoList {
+				chartInfoMap[v.ChartInfoId] = v
+			}
+		}
+		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 {
+								chartInfo, chartOk := chartInfoMap[crossItem.ChartInfoId]
+								if !chartOk { //表示图表不存在
+									continue
+								}
+								// 查询真正有用的指标ID
+								var config cross_variety.ChartConfigReq
+								e := json.Unmarshal([]byte(chartInfo.ExtraConfig), &config)
+								if e != nil {
+									continue
+								}
+								if utils.InArrayByInt(config.VarietyList, tag.ChartVarietyId) {
+									chartInfoCrossMap[crossItem.ChartInfoId] = struct{}{}
+									chartInfoCrossList = append(chartInfoCrossList, crossItem)
+								}
+							}
+						}
+					}
+				}
+			}
+			edbCrossMap[v.EdbInfoId] = chartInfoCrossList
+			chartInfoCrossMap = make(map[int]struct{})
+			chartInfoCrossList = make([]*cross_variety.ChartInfoCrossVariety, 0)
+		}
+
+		//查询引用关系列表,
+		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
+					}
+					// 去掉预测指标
+					if edbInfo.EdbInfoType == 1 {
+						continue
+					}
+					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 == 0 {
+						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 {
+			// 去掉预测指标
+			if edbInfo.EdbInfoType == 1 {
+				continue
+			}
+			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 == 0 {
+							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
+				}
+				// 去掉预测指标
+				if edbInfo.EdbInfoType == 1 {
+					continue
+				}
+				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 == 0 {
+					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
+					}
+					// 去掉预测指标
+					if edbInfo.EdbInfoType == 1 {
+						continue
+					}
+					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 == 0 {
+						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 == 0 { //普通计算指标,排除预算指标
+			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 == 0 {
+			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
+}
+
+// GetCalculateEdbByFromEdbInfo 找到依赖于该基础指标的所有计算指标
+func GetCalculateEdbByFromEdbInfo(edbInfoIds []int, calculateEdbIds []int, hasFind map[int]struct{}) (newCalculateEdbIds []int, err error) {
+	if len(edbInfoIds) == 0 {
+		return
+	}
+	newCalculateEdbIds = calculateEdbIds
+	newEdbInfoIds := make([]int, 0)
+	for _, v := range edbInfoIds {
+		if _, ok := hasFind[v]; ok {
+			continue
+		}
+		newEdbInfoIds = append(newEdbInfoIds, v)
+	}
+	if len(newEdbInfoIds) == 0 {
+		return
+	}
+	var condition string
+	var pars []interface{}
+	// 关联指标
+	condition += ` AND b.from_edb_info_id in (` + utils.GetOrmInReplace(len(newEdbInfoIds)) + `)`
+	pars = append(pars, newEdbInfoIds)
+
+	//获取关联图表列表
+	list, err := data_manage.GetRelationEdbInfoListMappingByCondition(condition, pars)
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		err = fmt.Errorf("获取关联指标信息失败,Err:%s", err.Error())
+		return
+	}
+	calculateEdbIdsTmp := make([]int, 0)
+	for _, mapping := range list {
+		if mapping.EdbType == 2 && mapping.EdbInfoType == 0 { // 如果指标库里的计算指标,则加入,否则继续找
+			newCalculateEdbIds = append(newCalculateEdbIds, mapping.EdbInfoId)
+			calculateEdbIdsTmp = append(calculateEdbIdsTmp, mapping.EdbInfoId)
+		}
+	}
+	for _, v := range newEdbInfoIds {
+		hasFind[v] = struct{}{}
+	}
+	if len(calculateEdbIdsTmp) > 0 {
+		newCalculateEdbIds, err = GetCalculateEdbByFromEdbInfo(calculateEdbIdsTmp, newCalculateEdbIds, hasFind)
+		if err != nil {
+			return
+		}
+	}
+
+	return
+}

+ 227 - 86
services/report.go

@@ -3,6 +3,7 @@ package services
 import (
 	"errors"
 	"eta/eta_task/models"
+	"eta/eta_task/models/report"
 	"eta/eta_task/services/alarm_msg"
 	"eta/eta_task/utils"
 	"fmt"
@@ -30,45 +31,17 @@ func UpdateReportEs(reportId int, publishState int) (err error) {
 			return
 		}
 		if len(chapterList) > 0 {
-			for i := 0; i < len(chapterList); i++ {
-				// 章节对应的品种
-				permissionList, tmpErr := models.GetChapterTypePermissionByTypeIdAndResearchType(chapterList[i].TypeId, chapterList[i].ReportType)
-				if tmpErr != nil {
-					return
-				}
-				categoryArr := make([]string, 0)
-				if len(permissionList) > 0 {
-					for ii := 0; ii < len(permissionList); ii++ {
-						categoryArr = append(categoryArr, permissionList[ii].PermissionName)
-					}
-				}
-				aliasArr, _ := addCategoryAliasToArr(categoryArr)
-				chapterCategories := strings.Join(aliasArr, ",")
-
-				esChapter := &models.ElasticReportDetail{
-					ReportId:           chapterList[i].ReportId,
-					ReportChapterId:    chapterList[i].ReportChapterId,
-					Title:              chapterList[i].Title,
-					Abstract:           chapterList[i].Abstract,
-					BodyContent:        utils.TrimHtml(html.UnescapeString(chapterList[i].Content)),
-					PublishTime:        chapterList[i].PublishTime.Format(utils.FormatDateTime),
-					PublishState:       chapterList[i].PublishState,
-					Author:             chapterList[i].Author,
-					ClassifyIdFirst:    chapterList[i].ClassifyIdFirst,
-					ClassifyNameFirst:  chapterList[i].ClassifyNameFirst,
-					ClassifyIdSecond:   0,
-					ClassifyNameSecond: "",
-					Categories:         chapterCategories,
-					StageStr:           strconv.Itoa(chapterList[i].Stage),
-				}
-				chapterDocId := fmt.Sprintf("%d-%d", reportInfo.Id, chapterList[i].ReportChapterId)
-				if err = EsAddOrEditReport(utils.EsReportIndexName, chapterDocId, esChapter); err != nil {
+			// 更新章节的es数据
+			for _, chapterInfo := range chapterList {
+				err = updateReportChapterEsByChapter(chapterInfo)
+				if err != nil {
 					return
 				}
 			}
 		}
 	} else {
-		permissionList, tmpErr := models.GetChartPermissionNameFromMappingByKeyword(reportInfo.ClassifyNameSecond, "rddp")
+		//if utils.BusinessCode == utils.BusinessCodeRelease || utils.BusinessCode == utils.BusinessCodeSandbox {
+		permissionList, tmpErr := models.GetChartPermissionNameFromMappingByKeyword("rddp", reportInfo.ClassifyIdSecond)
 		if tmpErr != nil {
 			return
 		}
@@ -78,6 +51,13 @@ func UpdateReportEs(reportId int, publishState int) (err error) {
 		}
 		aliasArr, _ := addCategoryAliasToArr(categoryArr)
 		categories = strings.Join(aliasArr, ",")
+		//}
+	}
+
+	// 最小单位的分类id
+	minClassifyId, minClassifyName, err := getMinClassify(reportInfo)
+	if err != nil {
+		return
 	}
 
 	// 新增报告ES
@@ -94,6 +74,8 @@ func UpdateReportEs(reportId int, publishState int) (err error) {
 		ClassifyNameFirst:  reportInfo.ClassifyNameFirst,
 		ClassifyIdSecond:   reportInfo.ClassifyIdSecond,
 		ClassifyNameSecond: reportInfo.ClassifyNameSecond,
+		ClassifyId:         minClassifyId,
+		ClassifyName:       minClassifyName,
 		Categories:         categories,
 		StageStr:           strconv.Itoa(reportInfo.Stage),
 	}
@@ -139,8 +121,58 @@ func addCategoryAliasToArr(categoryArr []string) (aliasArr []string, err error)
 	return
 }
 
+// updateReportChapterEsByChapter
+// @Description: 通过章节详情更新报告章节ES
+// @author: Roc
+// @datetime 2024-06-20 13:16:11
+// @param chapterInfo *models.ReportChapter
+// @return err error
+func updateReportChapterEsByChapter(chapterInfo *models.ReportChapter) (err error) {
+	// 章节对应的品种
+	obj := report.ReportChapterPermissionMapping{}
+	permissionList, tmpErr := obj.GetPermissionItemListById(chapterInfo.ReportChapterId)
+	if tmpErr != nil {
+		return
+	}
+	categoryArr := make([]string, 0)
+	if len(permissionList) > 0 {
+		for ii := 0; ii < len(permissionList); ii++ {
+			categoryArr = append(categoryArr, permissionList[ii].ChartPermissionName)
+		}
+	}
+	aliasArr, _ := addCategoryAliasToArr(categoryArr)
+	categories := strings.Join(aliasArr, ",")
+	// 新增/编辑ES
+
+	esChapter := &models.ElasticReportDetail{
+		ReportId:           chapterInfo.ReportId,
+		ReportChapterId:    chapterInfo.ReportChapterId,
+		Title:              chapterInfo.Title,
+		Abstract:           chapterInfo.Abstract,
+		BodyContent:        utils.TrimHtml(html.UnescapeString(chapterInfo.Content)),
+		PublishTime:        chapterInfo.PublishTime.Format(utils.FormatDateTime),
+		PublishState:       chapterInfo.PublishState,
+		Author:             chapterInfo.Author,
+		ClassifyIdFirst:    chapterInfo.ClassifyIdFirst,
+		ClassifyNameFirst:  chapterInfo.ClassifyNameFirst,
+		ClassifyIdSecond:   0,
+		ClassifyNameSecond: "",
+		ClassifyId:         chapterInfo.ClassifyIdFirst,
+		ClassifyName:       chapterInfo.ClassifyNameFirst,
+		Categories:         categories,
+		StageStr:           strconv.Itoa(chapterInfo.Stage),
+	}
+	chapterDocId := fmt.Sprintf("%d-%d", chapterInfo.ReportId, chapterInfo.ReportChapterId)
+	if err = EsAddOrEditReport(utils.EsReportIndexName, chapterDocId, esChapter); err != nil {
+		return
+	}
+
+	return
+}
+
 // PublishReport 定时发布研报-每秒
 func PublishReport(cont context.Context) (err error) {
+	errMsgList := make([]string, 0)
 	defer func() {
 		if err != nil {
 			go alarm_msg.SendAlarmMsg("PublishReport-定时发布研报失败, ErrMsg:\n"+err.Error(), 3)
@@ -171,41 +203,72 @@ func PublishReport(cont context.Context) (err error) {
 		if item.HasChapter == 1 && (item.ChapterType == utils.REPORT_TYPE_DAY || item.ChapterType == utils.REPORT_TYPE_WEEK) {
 			continue
 		}
-		if err = models.PublishReportById(item.Id, publishTime); err != nil {
-			return
+
+		var tmpErr error
+		if item.HasChapter == 1 { // 章节类型的报告
+			// 发布报告和章节
+			item.State = 2
+			item.PublishTime = publishTime
+			item.ModifyTime = time.Now().Local()
+			updateCols := make([]string, 0)
+			updateCols = append(updateCols, "Title", "State", "ModifyTime")
+			tmpErr = models.PublishReportAndChapter(item, true, updateCols)
+		} else {
+			tmpErr = models.PublishReportById(item.Id, publishTime)
+		}
+		if tmpErr != nil {
+			errMsgList = append(errMsgList, fmt.Sprint("报告发布失败,ID:", item.Id, ",ErrMsg:", tmpErr.Error()))
+		} else {
+			go handleByPublishReport(item)
 		}
+	}
 
-		go func() {
-			// 生成音频
-			if item.VideoUrl == "" {
-				_ = CreateVideo(item)
-			}
-			//// 推送找钢网
-			//if utils.RunMode == "release" && (report.ClassifyNameSecond == "知白守黑日评" || report.ClassifyNameSecond == "股债日评") {
-			//	_ = services.ZhaoGangSend(report)
-			//}
-			// 更新报告Es
-			_ = UpdateReportEs(item.Id, 2)
-
-			// 判断是否未发送模版消息,并且配置了立即推送模版消息的报告需要推送
-			if utils.SendWxTemplateEnable == "1" {
-				if item.MsgIsSend == 0 && item.PreMsgSend == 1 {
-					_ = ReportSendTemplateMsg(item.Id)
-				}
-			}
-		}()
-		recordItem := &models.ReportStateRecord{
-			ReportId:   item.Id,
-			ReportType: 1,
-			State:      2,
-			AdminId:    item.AdminId,
-			AdminName:  item.AdminName,
-			CreateTime: time.Now(),
-		}
-		go func() {
-			_, _ = models.AddReportStateRecord(recordItem)
-		}()
+	return
+}
+
+// handleByPublishReport
+// @Description: 报告发布
+// @author: Roc
+// @datetime 2024-06-28 13:26:51
+// @param item *models.Report
+// @param publishTime time.Time
+// @return err error
+func handleByPublishReport(item *models.Report) {
+	recordItem := &models.ReportStateRecord{
+		ReportId:   item.Id,
+		ReportType: 1,
+		State:      2,
+		AdminId:    item.AdminId,
+		AdminName:  item.AdminName,
+		CreateTime: time.Now(),
+	}
+
+	// 添加记录
+	_, _ = models.AddReportStateRecord(recordItem)
+
+	if item.HasChapter == 1 {
+		// 生产报告章节音频
+		_ = UpdateChaptersVideoByReportId(item.Id)
+	} else {
+		// 生成音频
+		if item.VideoUrl == "" {
+			_ = CreateVideo(item)
+		}
 	}
+
+	// 更新报告Es
+	err := UpdateReportEs(item.Id, 2)
+	if err != nil {
+		utils.FileLog.Error("UpdateReportEs, 更新报告Es失败, ReportId:%s, Err:%s", item.Id, err.Error())
+	}
+
+	// 判断是否未发送模版消息,并且配置了立即推送模版消息的报告需要推送
+	if utils.SendWxTemplateEnable == "1" {
+		if item.MsgIsSend == 0 && item.PreMsgSend == 1 {
+			_ = ReportSendTemplateMsg(item.Id)
+		}
+	}
+
 	return
 }
 
@@ -239,12 +302,12 @@ func ReportSendTemplateMsg(reportId int) (err error) {
 		}
 	}()
 
-	report, err := models.GetReportById(reportId)
+	reportInfo, err := models.GetReportByReportId(reportId)
 	if err != nil {
 		err = errors.New("查询报告失败 Err:" + err.Error())
 		return
 	}
-	if report.MsgIsSend == 1 {
+	if reportInfo.MsgIsSend == 1 {
 		err = errors.New("模板消息已推送,请勿重复操作")
 		return
 	}
@@ -255,7 +318,7 @@ func ReportSendTemplateMsg(reportId int) (err error) {
 		err = errors.New("修改发布时间失败,Err:" + err.Error())
 		return
 	}
-	if report.HasChapter > 0 {
+	if reportInfo.HasChapter > 0 {
 		err = models.UpdateReportChapterPublishTime(reportId, videoNameDate)
 		if err != nil {
 			err = errors.New("修改发布时间失败,Err:" + err.Error())
@@ -263,7 +326,7 @@ func ReportSendTemplateMsg(reportId int) (err error) {
 		}
 	}
 
-	err = sendMiniProgramReportWxMsg(report)
+	err = sendMiniProgramReportWxMsg(reportInfo)
 	if err != nil {
 		err = errors.New("发送失败,Err:" + err.Error())
 		return
@@ -277,7 +340,7 @@ func ReportSendTemplateMsg(reportId int) (err error) {
 }
 
 // sendMiniProgramReportWxMsg 推送报告微信模板消息-小程序链接
-func sendMiniProgramReportWxMsg(report *models.ReportDetail) (err error) {
+func sendMiniProgramReportWxMsg(report *models.Report) (err error) {
 	reportId := report.Id
 	var msg string
 	reportIdStr := strconv.Itoa(reportId)
@@ -297,33 +360,36 @@ func sendMiniProgramReportWxMsg(report *models.ReportDetail) (err error) {
 	}
 
 	var openIdArr []string
-	if report.ClassifyIdSecond <= 0 {
+	// 如果是弘则,且报告分类是晨报,那么就所有人推送
+	if (utils.BusinessCode == utils.BusinessCodeRelease || utils.BusinessCode == utils.BusinessCodeSandbox || utils.BusinessCode == utils.BusinessCodeDebug) && report.ClassifyNameFirst == "晨报" {
+		// 如果是章节,那就推送所有用户
 		openIdArr, err = models.GetOpenIdArr()
 		if err != nil {
 			msg = "get GetOpenIdArr err:" + err.Error()
 			return
 		}
 	} else {
-		classify, err := models.GetClassifyById(report.ClassifyIdSecond)
+		minClassifyId, _, err := getMinClassify(report)
+		if err != nil {
+			msg = "获取报告的最小分类失败 err:" + err.Error()
+			return err
+		}
+
+		// 判断分类是否存在
+		_, err = models.GetClassifyById(minClassifyId)
 		if err != nil {
 			msg = "获取报告分类失败 err:" + err.Error()
 			return err
 		}
-		if classify.IsMassSend == 1 {
-			openIdArr, err = models.GetOpenIdArr()
-			if err != nil {
-				msg = "get GetOpenIdArr err:" + err.Error()
-				return err
-			}
-		} else {
-			openIdArr, err = models.GetOpenIdArrByClassifyNameSecond(report.ClassifyNameSecond)
-			if err != nil {
-				msg = "GetOpenIdArrByClassifyNameSecond err:" + err.Error()
-				return err
-			}
+		// 获取该分类关联的openid列表
+		openIdArr, err = models.GetOpenIdArrByClassifyId(minClassifyId)
+		if err != nil {
+			msg = "GetOpenIdArrByClassifyNameSecond err:" + err.Error()
+			return err
 		}
 	}
 
+	// TODO 弘则的文案是不是要去掉
 	title := fmt.Sprintf("弘则%s", report.ClassifyNameFirst)
 	if CheckTwoWeekOrMonthReport(report.ClassifyIdFirst, report.ClassifyNameFirst) {
 		title = fmt.Sprintf("弘则%s", report.ClassifyNameSecond)
@@ -332,7 +398,7 @@ func sendMiniProgramReportWxMsg(report *models.ReportDetail) (err error) {
 	first := fmt.Sprintf("Hi,最新一期%s已上线,欢迎查看", report.ClassifyNameFirst)
 	keyword1 := title
 	keyword2 := report.Title
-	keyword3 := report.PublishTime
+	keyword3 := report.PublishTime.Format(utils.FormatDateTime)
 	keyword4 := report.Abstract
 
 	var wxAppPath string
@@ -397,3 +463,78 @@ func ClearReportSaveLog(cont context.Context) (err error) {
 	}
 	return
 }
+
+// UpdateChaptersVideoByReportId
+// @Description: 更新报告章节音频
+// @author: Roc
+// @datetime 2024-06-28 13:52:56
+// @param reportId int
+// @return err error
+func UpdateChaptersVideoByReportId(reportId int) (err error) {
+	defer func() {
+		if err != nil {
+			utils.FileLog.Error("UpdateChaptersVideo, reportId:%v, Err:%s", reportId, err.Error())
+			go alarm_msg.SendAlarmMsg(fmt.Sprintf("更新章节音频失败, 报告ID: %v; Err: "+err.Error(), reportId), 3)
+		}
+	}()
+	chapterList, err := models.GetChapterListByReportId(reportId)
+	if err != nil {
+		return
+	}
+	// 生成video
+	nowTime := time.Now()
+	updateCols := make([]string, 0)
+	updateCols = append(updateCols, "VideoUrl", "VideoName", "VideoSize", "VideoPlaySeconds")
+	for i := 0; i < len(chapterList); i++ {
+		item := chapterList[i]
+		// 忽略已有音频的章节
+		if item.VideoUrl != "" && item.VideoName != "" && item.VideoSize != "" && item.VideoPlaySeconds != "" {
+			continue
+		}
+		videoUrl, videoName, videoSize, videoPlaySeconds, e := CreateReportVideo(item.Title, html.UnescapeString(item.Content), nowTime.Format(utils.FormatDateTime))
+		if e != nil {
+			err = e
+			return
+		}
+		item.VideoUrl = videoUrl
+		item.VideoName = videoName
+		item.VideoSize = videoSize
+		item.VideoPlaySeconds = fmt.Sprintf("%.2f", videoPlaySeconds)
+		if e = item.UpdateChapter(updateCols); e != nil {
+			err = e
+		}
+	}
+
+	return
+}
+
+// getMinClassify
+// @Description: 获取最小分类ID
+// @author: Roc
+// @datetime 2024-06-20 09:23:19
+// @param reportInfo *models.Report
+// @return minClassifyId int
+// @return minClassifyName string
+// @return err error
+func getMinClassify(reportInfo *models.Report) (minClassifyId int, minClassifyName string, err error) {
+	defer func() {
+		if err != nil {
+			utils.FileLog.Error("获取最小分类ID失败,报告ID:%d,Err:%s", reportInfo.Id, err.Error())
+		}
+	}()
+	minClassifyId = reportInfo.ClassifyIdThird
+	minClassifyName = reportInfo.ClassifyNameThird
+	if minClassifyId <= 0 {
+		minClassifyId = reportInfo.ClassifyIdSecond
+		minClassifyName = reportInfo.ClassifyNameSecond
+	}
+	if minClassifyId <= 0 {
+		minClassifyId = reportInfo.ClassifyIdFirst
+		minClassifyName = reportInfo.ClassifyNameFirst
+	}
+	if minClassifyId <= 0 {
+		err = errors.New("分类异常")
+	}
+
+	return
+}

+ 10 - 0
services/task.go

@@ -58,6 +58,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)
@@ -188,6 +192,12 @@ func RefreshData(cont context.Context) (err error) {
 	// 预测计算指标
 	data.RefreshPredictDataFromCalculateAll()
 
+	// 指标系列计算数据
+	_ = data.RefreshFactorEdbCalculateData()
+
+	// 指标系列图表计算数据
+	_ = data.RefreshFactorEdbChartCalculateData()
+
 	time.Sleep(5 * time.Second)
 	//data.RefreshNotice()
 

+ 34 - 0
utils/constants.go

@@ -144,7 +144,9 @@ const (
 
 // 商户号
 const (
+	BusinessCodeSandbox = "E2023080700" // 试用平台
 	BusinessCodeRelease = "E2023080900" // 生产环境
+	BusinessCodeDebug   = "E2023080901" // 测试环境
 	BusinessCodeJiaYue  = "E2023092201" // 嘉悦物产
 	BusinessCodeZhongJi = "E2023110300" // 中基宁波
 )
@@ -157,3 +159,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 // 平衡表
+)