فهرست منبع

Merge branch 'feature/eta2.6.5_kpler' into debug

# Conflicts:
#	routers/router.go
xyxie 3 روز پیش
والد
کامیت
abe8b2ea23

+ 284 - 0
controllers/base_from_kpler.go

@@ -0,0 +1,284 @@
+package controllers
+
+import (
+	"encoding/json"
+	"eta/eta_index_lib/logic"
+	"eta/eta_index_lib/models"
+	"eta/eta_index_lib/services"
+	"eta/eta_index_lib/utils"
+	"fmt"
+	"strconv"
+	"strings"
+	"time"
+)
+
+// KplerController Kpler数据
+type KplerController struct {
+	BaseAuthController
+}
+
+// GetData
+// @Title 开普勒数据-获取数据
+// @Description 开普勒数据-获取数据
+// @Success 200 {object} models.ThsHfSearchEdbReq
+// @router /edb_data [post]
+func (this *KplerController) GetData() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var params models.KplerSearchEdbReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &params); e != nil {
+		br.Msg = "参数解析异常"
+		br.ErrMsg = fmt.Sprintf("参数解析失败, %v", e)
+		return
+	}
+	params.Granularity = strings.TrimSpace(params.Granularity)
+	if params.Granularity == "" {
+		br.Msg = "请选择频度"
+		return
+	}
+	split := strings.TrimSpace(params.Split)
+	if split == "" {
+		split = "Total"
+	}
+	unit := strings.TrimSpace(params.Unit)
+	if unit == "" {
+		unit = "Kbd"
+	}
+	flowDirection := strings.TrimSpace(params.FlowDirection)
+	if flowDirection == "" {
+		br.Msg = "请选择流向"
+		return
+	}
+	
+	// 根据配置获取指标数据
+	indexes, _, e := services.GetKplerDataByApi(params, "")
+	if e != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = fmt.Sprintf("获取开普勒高频指标失败, %v", e)
+		return
+	}
+
+	br.Data = indexes
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+}
+// 批量新增指标
+// @Title 批量新增指标
+// @Description 批量新增指标
+// @Success 200 {object} models.KplerSearchEdbReq
+// @router /index_add [post]
+func (this *KplerController) IndexAdd() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	
+	var params models.KplerSearchEdbReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &params); e != nil {
+		br.Msg = "参数解析异常"
+		br.ErrMsg = fmt.Sprintf("参数解析失败, %v", e)
+		return
+	}
+	params.Granularity = strings.TrimSpace(params.Granularity)
+	if params.Granularity == "" {
+		br.Msg = "请选择频度"
+		return
+	}
+	split := strings.TrimSpace(params.Split)
+	if split == "" {
+		split = "Total"
+	}
+	unit := strings.TrimSpace(params.Unit)
+	if unit == "" {
+		unit = "Kbd"
+	}
+	flowDirection := strings.TrimSpace(params.FlowDirection)
+	if flowDirection == "" {
+		br.Msg = "请选择流向"
+		return
+	}
+	
+	// 根据配置获取指标数据
+	indexes, terminalInfo, e := services.GetKplerDataByApi(params, "")
+	if e != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = fmt.Sprintf("获取开普勒高频指标失败, %v", e)
+		return
+	}
+	
+	// 批量新增指标
+	err := services.AddKplerIndexByApi(indexes, &params, 0, terminalInfo.TerminalCode)
+	if err != nil {
+		br.Msg = "新增失败"
+		br.ErrMsg = fmt.Sprintf("新增失败, %v", err)
+		return
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "新增成功"
+}
+
+// Add
+// @Title 新增Kpler指标接口
+// @Description 新增Kpler指标接口
+// @Success 200 {object} models.AddEdbInfoReq
+// @router /add [post]
+func (this *KplerController) Add() {
+	br := new(models.BaseResponse).Init()
+	var cacheKey string
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	kpler := new(models.BaseFromKpler)
+	source := kpler.GetSource()
+	var req models.AddEdbInfoReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.EdbCode == "" {
+		br.Msg = "请输入指标编码!"
+		br.ErrMsg = "请输入指标编码,指标编码为空"
+		return
+	}
+	cacheKey = utils.CACHE_EDB_DATA_ADD + strconv.Itoa(source) + "_" + req.EdbCode
+	if utils.Rc.IsExist(cacheKey) {
+		br.Ret = 501
+		br.Success = true
+		br.Msg = "系统处理中,请稍后重试"
+		return
+	}
+	utils.Rc.SetNX(cacheKey, 1, 1*time.Minute)
+	defer func() {
+		utils.Rc.Delete(cacheKey)
+	}()
+	err = kpler.Add(req.EdbCode)
+	if err != nil {
+		br.Msg = "获取指标信息失败!"
+		br.ErrMsg = "获取指标信息失败 AddEdbDataFromKpler,Err:" + err.Error()
+		return
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	return
+}
+
+// Refresh
+// @Title 刷新Kpler指标接口
+// @Description 刷新Kpler指标接口
+// @Success 200 {object} models.RefreshEdbInfoReq
+// @router /refresh [post]
+func (this *KplerController) Refresh() {
+	br := new(models.BaseResponse).Init()
+	var cacheKey string
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	kpler := new(models.BaseFromKpler)
+	source := kpler.GetSource()
+	var req models.RefreshEdbInfoReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.EdbCode == "" {
+		br.Msg = "请输入指标编码!"
+		br.ErrMsg = "请输入指标编码,指标编码为空"
+		return
+	}
+	if req.EdbInfoId < 0 {
+		br.Msg = "请输入指标ID!"
+		br.ErrMsg = "请输入指标ID"
+		return
+	}
+
+	// 获取指标详情
+	edbInfo, err := models.GetEdbInfoByEdbCode(source, req.EdbCode)
+	if err != nil {
+		br.Msg = "指标不存在!"
+		br.ErrMsg = "指标不存在"
+		return
+	}
+	cacheKey = utils.CACHE_EDB_DATA_REFRESH + strconv.Itoa(source) + "_" + req.EdbCode
+	if utils.Rc.IsExist(cacheKey) {
+		br.Ret = 501
+		br.Success = true
+		br.Msg = "系统处理中,请稍后重试"
+		return
+	}
+	utils.Rc.SetNX(cacheKey, 1, 1*time.Minute)
+	defer func() {
+		utils.Rc.Delete(cacheKey)
+	}()
+	if req.EdbInfoId <= 0 {
+		req.EdbInfoId = edbInfo.EdbInfoId
+	}
+	err = kpler.Refresh(req.EdbInfoId, req.EdbCode, req.StartDate)
+	if err != nil && !utils.IsErrNoRow(err) {
+		br.Msg = "刷新指标信息失败!"
+		br.ErrMsg = "刷新指标信息失败 RefreshEdbDataFromKpler,Err:" + err.Error()
+		return
+	}
+	// 更新指标最大最小值
+	err, errMsg := models.UnifiedModifyEdbInfoMaxAndMinInfo(edbInfo)
+	if err != nil {
+		br.Msg = errMsg
+		br.ErrMsg = err.Error()
+		return
+	}
+
+	// 更新ES
+	go logic.UpdateEs(edbInfo.EdbInfoId)
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+}
+
+// HandleExcelData
+// @Title 处理Kpler指标的接口
+// @Description 处理Kpler指标的接口
+// @Success 200 {object} models.HandleKplerExcelDataReq
+// @router /handle/excel_data [post]
+func (this *KplerController) HandleExcelData() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req models.HandleKplerExcelDataReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	// 处理excel表数据
+	err = services.HandleKplerIndex(&req)
+	if err != nil {
+		fmt.Println("HandleKplerIndex Err:" + err.Error())
+		br.Msg = "处理失败"
+		br.ErrMsg = "处理失败,Err:" + err.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "处理成功"
+}

+ 3 - 0
logic/base_edb_info.go

@@ -50,6 +50,9 @@ func RefreshBaseEdbInfo(edbInfo *models.EdbInfo, startDate string) (isHandling b
 	case utils.DATA_SOURCE_PuRang:
 		ob := new(models.BaseFromPurang)
 		err = ob.Refresh(edbInfo.EdbInfoId, edbInfo.EdbCode, startDate)
+	case utils.DATA_SOURCE_KPLER:
+		ob := new(models.BaseFromKpler)
+		err = ob.Refresh(edbInfo.EdbInfoId, edbInfo.EdbCode, startDate)
 	default:
 		return
 	}

+ 604 - 0
models/base_from_kpler.go

@@ -0,0 +1,604 @@
+package models
+
+import (
+	sql2 "database/sql"
+	"eta/eta_index_lib/global"
+	"eta/eta_index_lib/utils"
+	"fmt"
+	"gorm.io/gorm"
+	"strconv"
+	"strings"
+	"time"
+)
+
+// BaseFromKpler Kpler数据
+type BaseFromKpler struct{}
+
+type BaseFromKplerData struct {
+	BaseFromKplerDataId int `gorm:"column:base_from_kpler_data_id;primaryKey"`
+	//BaseFromKplerDataId  int `orm:"column(base_from_kpler_data_id);pk"`
+	BaseFromKplerIndexId int
+	IndexCode            string
+	DataTime             string
+	Value                string
+	CreateTime           time.Time
+	ModifyTime           time.Time
+	DataTimestamp        int64
+}
+
+func (e *BaseFromKplerData) AfterFind(db *gorm.DB) (err error) {
+	e.DataTime = utils.GormDateStrToDateStr(e.DataTime)
+
+	return
+}
+
+func GetBaseFromKplerDataByCondition(condition string, pars []interface{}) (list []*BaseFromKplerData, err error) {
+	//o := orm.NewOrm()
+	sql := `SELECT * FROM base_from_kpler_data WHERE 1=1 `
+	if condition != "" {
+		sql += condition
+	}
+	//_, err = o.Raw(sql, pars).QueryRows(&list)
+	err = global.DEFAULT_DB.Raw(sql, pars...).Find(&list).Error
+	return
+}
+
+// Add 添加
+func (obj BaseFromKpler) Add(edbCode string) (err error) {
+	//o := orm.NewOrm()
+
+	var condition string
+	var pars []interface{}
+	if edbCode != "" {
+		condition += " AND index_code=? "
+		pars = append(pars, edbCode)
+	}
+	KplerBaseDataAll, err := GetBaseFromKplerDataByCondition(condition, pars)
+	if err != nil && !utils.IsErrNoRow(err) {
+		return
+	}
+	var isAdd bool
+	addSql := ` INSERT INTO edb_data_kpler(edb_info_id,edb_code,data_time,value,create_time,modify_time,data_timestamp) values `
+	existMap := make(map[string]string)
+	for _, sv := range KplerBaseDataAll {
+		eDate := sv.DataTime
+		dataTime, err := time.Parse(utils.FormatDate, eDate)
+		if err != nil {
+			return err
+		}
+		timestamp := dataTime.UnixNano() / 1e6
+		timeStr := fmt.Sprintf("%d", timestamp)
+		if _, ok := existMap[eDate]; !ok {
+			addSql += GetAddSql("0", edbCode, eDate, timeStr, sv.Value)
+			isAdd = true
+		}
+		existMap[eDate] = sv.Value
+	}
+	if isAdd {
+		addSql = strings.TrimRight(addSql, ",")
+		utils.FileLog.Info("addSql:" + addSql)
+		//_,err=o.Raw(addSql).Exec()
+		err = global.DEFAULT_DB.Exec(addSql).Error
+		if err != nil {
+			return err
+		}
+	}
+	return
+}
+
+// Refresh 刷新Kpler指标数据
+func (obj BaseFromKpler) Refresh(edbInfoId int, edbCode, startDate string) (err error) {
+	source := obj.GetSource()
+	//o := orm.NewOrm()
+	if err != nil {
+		return
+	}
+	edbInfoIdStr := strconv.Itoa(edbInfoId)
+	//计算数据
+	var condition string
+	var pars []interface{}
+
+	if edbCode != "" {
+		condition += " AND index_code=? "
+		pars = append(pars, edbCode)
+	}
+
+	if startDate != "" {
+		condition += " AND data_time>=? "
+		pars = append(pars, startDate)
+	}
+
+	KplerDataList, err := GetBaseFromKplerDataByCondition(condition, pars)
+	if err != nil {
+		return
+	}
+
+	// 真实数据的最大日期  , 插入规则配置的日期
+	var realDataMaxDate, edbDataInsertConfigDate time.Time
+	var edbDataInsertConfig *EdbDataInsertConfig
+	var isFindConfigDateRealData bool //是否找到配置日期的实际数据的值
+	{
+		edbDataInsertConfig, err = GetEdbDataInsertConfigByEdbId(edbInfoId)
+		if err != nil && !utils.IsErrNoRow(err) {
+			return
+		}
+		if edbDataInsertConfig != nil {
+			edbDataInsertConfigDate = edbDataInsertConfig.Date
+		}
+	}
+
+	var existCondition string
+	var existPars []interface{}
+
+	existCondition += " AND edb_info_id=? "
+	existPars = append(existPars, edbInfoId)
+	if startDate != "" {
+		existCondition += " AND data_time>=? "
+		existPars = append(existPars, startDate)
+	}
+
+	existList, err := GetEdbDataByCondition(source, 0, existCondition, existPars)
+	if err != nil {
+		return err
+	}
+	existMap := make(map[string]*EdbInfoSearchData)
+	for _, v := range existList {
+		existMap[v.DataTime] = v
+	}
+	addSql := ` INSERT INTO edb_data_kpler(edb_info_id,edb_code,data_time,value,create_time,modify_time,data_timestamp) values `
+	var isAdd bool
+	for _, v := range KplerDataList {
+		item := v
+		eDate := item.DataTime
+		dataTime, err := time.ParseInLocation(utils.FormatDate, eDate, time.Local)
+		if err != nil {
+			return err
+		}
+		if findItem, ok := existMap[v.DataTime]; !ok {
+			sValue := item.Value
+
+			timestamp := dataTime.UnixNano() / 1e6
+			timeStr := fmt.Sprintf("%d", timestamp)
+
+			addSql += GetAddSql(edbInfoIdStr, edbCode, eDate, timeStr, sValue)
+			isAdd = true
+		} else {
+			if findItem != nil && utils.SubFloatToString(findItem.Value, 30) != item.Value {
+				err = ModifyEdbDataById(source, 0, findItem.EdbDataId, item.Value)
+				if err != nil {
+					return err
+				}
+			}
+		}
+
+		// 下面代码主要目的是处理掉手动插入的数据判断
+		{
+			if realDataMaxDate.IsZero() || dataTime.After(realDataMaxDate) {
+				realDataMaxDate = dataTime
+			}
+			if edbDataInsertConfigDate.IsZero() || dataTime.Equal(edbDataInsertConfigDate) {
+				isFindConfigDateRealData = true
+			}
+		}
+	}
+
+	// 处理手工数据补充的配置
+	HandleConfigInsertEdbData(realDataMaxDate, edbDataInsertConfig, edbInfoId, source, 0, existMap, isFindConfigDateRealData)
+
+	if isAdd {
+		addSql = strings.TrimRight(addSql, ",")
+		//_,err = o.Raw(assSql).Exec()
+		err = global.DEFAULT_DB.Exec(addSql).Error
+		if err != nil {
+			fmt.Println("RefreshEdbDataFromKpler add Err", err.Error())
+			return
+		}
+	}
+	return
+}
+
+// GetSource 获取来源编码id
+func (obj BaseFromKpler) GetSource() int {
+	return utils.DATA_SOURCE_KPLER
+}
+
+// GetSourceName 获取来源名称
+func (obj BaseFromKpler) GetSourceName() string {
+	return utils.DATA_SOURCE_NAME_KPLER
+}
+
+type BaseFromKplerIndex struct {
+	BaseFromKplerIndexId int `gorm:"column:base_from_kpler_index_id;primaryKey"`
+	//BaseFromKplerIndexId int `orm:"column(base_from_kpler_index_id);pk"`
+	ClassifyId    int
+	IndexCode     string
+	IndexName     string
+	Frequency     string
+	Unit          string
+	Sort          int
+	StartDate     string `description:"开始日期"`
+	EndDate       string `description:"结束日期"`
+	EndValue      float64
+	CreateTime    time.Time
+	ModifyTime    time.Time
+	BaseFileName  string `description:"文件目录"`
+	TerminalCode  string `description:"所属终端编码"`
+	ApiQueryUrl   string `description:"API查询URL"`
+	ProductNames  string `description:"产品名称"`
+	FromZoneId    int    `description:"区域ID"`
+	FromZoneName  string `description:"区域名称"`
+	ToZoneId      int    `description:"区域ID"`
+	ToZoneName    string `description:"区域名称"`
+	FlowDirection string `description:"流向"`
+	Granularity   string `description:"粒度"`
+	Split         string `description:"拆分类型"`
+}
+
+func (e *BaseFromKplerIndex) AfterFind(db *gorm.DB) (err error) {
+	e.StartDate = utils.GormDateStrToDateStr(e.StartDate)
+	e.EndDate = utils.GormDateStrToDateStr(e.EndDate)
+
+	return
+}
+
+type BaseFromKplerIndexList struct {
+	BaseFromKplerIndexId int `gorm:"column:base_from_kpler_index_id;primaryKey"`
+	//BaseFromKplerIndexId int `orm:"column(base_from_kpler_index_id);pk"`
+	IndexCode     string
+	IndexName     string
+	Frequency     string
+	Unit          string
+	Sort          int
+	ClassifyId    int
+	StartDate     string
+	EndDate       string
+	TerminalCode  string
+	CreateTime    string
+	ModifyTime    string
+	ProductNames  string `description:"产品名称"`
+	FromZoneId    int    `description:"区域ID"`
+	FromZoneName  string `description:"区域名称"`
+	ToZoneId      int    `description:"区域ID"`
+	ToZoneName    string `description:"区域名称"`
+	FlowDirection string `description:"流向"`
+	Granularity   string `description:"粒度"`
+	Split         string `description:"拆分类型"`
+}
+
+// AfterFind 在该模型上设置钩子函数,把日期转成正确的string,所以查询函数只能用Find函数,First或者Scan是不会触发该函数的来获取数据
+func (m *BaseFromKplerIndexList) AfterFind(db *gorm.DB) (err error) {
+	m.StartDate = utils.GormDateStrToDateStr(m.StartDate)
+	m.EndDate = utils.GormDateStrToDateStr(m.EndDate)
+
+	return
+}
+
+func (y *BaseFromKplerIndex) GetByIndexCodes(indexCodes []string) (list []*BaseFromKplerIndex, err error) {
+	sql := ` SELECT * FROM base_from_kpler_index WHERE index_code in (?) `
+	err = global.DEFAULT_DB.Raw(sql, indexCodes).Find(&list).Error
+	return
+}
+
+func (y *BaseFromKplerData) GetByIndexCode(indexCode string) (list []*BaseFromKplerData, err error) {
+	//o := orm.NewOrm()
+	sql := ` SELECT * FROM base_from_kpler_data WHERE index_code=? `
+	//_, err = o.Raw(sql, indexCode).QueryRows(&list)
+	err = global.DEFAULT_DB.Raw(sql, indexCode).Find(&list).Error
+	return
+}
+
+func (y *BaseFromKplerData) AddMulti(item []*BaseFromKplerData) (err error) {
+	//o := orm.NewOrm()
+	//_, err = o.InsertMulti(1, item)
+	err = global.DEFAULT_DB.CreateInBatches(&item, 1).Error
+	return
+}
+
+// Update 修改
+func (y *BaseFromKplerData) Update(updateCols []string) (err error) {
+	//o := orm.NewOrm()
+	//_, err = o.Update(y, updateCols...)
+	err = global.DEFAULT_DB.Model(&y).Select(updateCols).Updates(&y).Error
+	return
+}
+
+// HandleKplerExcelData Kpler的excel数据
+type HandleKplerExcelData struct {
+	ClassifyName       string `description:"指标目录"`
+	ParentClassifyName string `description:"父级指标目录"`
+	ClassifySort       int    `description:"指标目录排序号"`
+	IndexName          string `description:"指标名称"`
+	IndexCode          string `description:"指标编码"`
+	Unit               string `description:"单位"`
+	Sort               int    `description:"排序号"`
+	Frequency          string `description:"频度"`
+	ProductNames       string `description:"产品名称"`
+	FromZoneId         int    `description:"区域ID"`
+	FromZoneName       string `description:"区域名称"`
+	ToZoneId           int    `description:"区域ID"`
+	ToZoneName         string `description:"区域名称"`
+	FlowDirection      string `description:"流向"`
+	Granularity        string `description:"粒度"`
+	Split              string `description:"拆分类型"`
+	ExcelDataMap       map[string]string
+}
+
+type HandleKplerExcelDataReq struct {
+	List         []*HandleKplerExcelData
+	TerminalCode string `description:"编码"`
+}
+
+func (y *BaseFromKplerData) GetMaxAndMinDateByIndexCode(indexCode string) (item *EdbInfoMaxAndMinInfo, err error) {
+	//o := orm.NewOrm()
+	sql := ` SELECT MIN(data_time) AS min_date,MAX(data_time) AS max_date,MIN(value) AS min_value,MAX(value) AS max_value FROM base_from_kpler_data WHERE index_code=? `
+	//err = o.Raw(sql, indexCode).QueryRow(&item)
+	err = global.DEFAULT_DB.Raw(sql, indexCode).First(&item).Error
+	sql = ` SELECT value AS latest_value FROM %s WHERE index_code=? ORDER BY data_time DESC LIMIT 1 `
+	sql = fmt.Sprintf(sql, "base_from_kpler_data")
+	//err = o.Raw(sql, indexCode).QueryRow(&latest_value)
+	var latestValueNull sql2.NullFloat64
+	err = global.DEFAULT_DB.Raw(sql, indexCode).Scan(&latestValueNull).Error
+	if err == nil && latestValueNull.Valid {
+		item.LatestValue = latestValueNull.Float64
+	}
+
+	return
+}
+
+func (y *BaseFromKplerIndex) ModifyIndexMaxAndMinDate(indexCode string, item *EdbInfoMaxAndMinInfo) (err error) {
+	//o := orm.NewOrm()
+	sql := ` UPDATE base_from_kpler_index SET start_date=?,end_date=?, end_value=?, modify_time=NOW() WHERE index_code=? `
+	//_, err = o.Raw(sql, item.MinDate, item.MaxDate, item.LatestValue, indexCode).Exec()
+	err = global.DEFAULT_DB.Exec(sql, item.MinDate, item.MaxDate, item.LatestValue, indexCode).Error
+	return
+}
+
+func (y *BaseFromKplerIndex) GetByIndexCode(indexCode string) (item *BaseFromKplerIndex, err error) {
+	//o := orm.NewOrm()
+	sql := ` SELECT * FROM base_from_kpler_index WHERE index_code=? `
+	//err = o.Raw(sql, indexCode).QueryRow(&item)
+	err = global.DEFAULT_DB.Raw(sql, indexCode).First(&item).Error
+	return
+}
+
+func (y *BaseFromKplerIndex) Add() (err error) {
+	//o := orm.NewOrm()
+	//lastId, err = o.Insert(y)
+	err = global.DEFAULT_DB.Create(&y).Error
+	if err != nil {
+		return
+	}
+	return
+}
+
+// Update 修改
+func (y *BaseFromKplerIndex) Update(updateCols []string) (err error) {
+	//o := orm.NewOrm()
+	//_, err = o.Update(y, updateCols...)
+	err = global.DEFAULT_DB.Model(&y).Select(updateCols).Updates(&y).Error
+	return
+}
+
+func (y *BaseFromKplerClassify) Add() (lastId int64, err error) {
+	//o := orm.NewOrm()
+	//lastId, err = o.Insert(y)
+	err = global.DEFAULT_DB.Create(&y).Error
+	if err != nil {
+		return
+	}
+	lastId = int64(y.ClassifyId)
+	return
+}
+
+// Update 修改
+func (y *BaseFromKplerClassify) Update(updateCols []string) (err error) {
+	//o := orm.NewOrm()
+	//_, err = o.Update(y, updateCols...)
+	err = global.DEFAULT_DB.Model(&y).Select(updateCols).Updates(&y).Error
+	return
+}
+
+func (y *BaseFromKplerClassify) GetByClassifyName(classifyName string) (item *BaseFromKplerClassify, err error) {
+	//o := orm.NewOrm()
+	sql := ` SELECT * FROM base_from_kpler_classify WHERE classify_name=? `
+	//err = o.Raw(sql, classifyName).QueryRow(&item)
+	err = global.DEFAULT_DB.Raw(sql, classifyName).First(&item).Error
+	return
+}
+
+func (y *BaseFromKplerClassify) GetParentClassify() (items []*BaseFromKplerClassify, err error) {
+	//o := orm.NewOrm()
+	sql := ` SELECT * FROM base_from_kpler_classify WHERE parent_id=0 `
+	//_, err = o.Raw(sql).QueryRows(&items)
+	err = global.DEFAULT_DB.Raw(sql).Find(&items).Error
+	return
+}
+
+type KplerSearchEdbReq struct {
+	ProductNames string `description:"产品名称"`
+	FromZoneIds []int `description:"来源区域ID,对应Location" ` 
+	FromZoneNames string `description:"来源区域名称"`
+	ToZoneIds []int `description:"流向区域ID"`
+	ToZoneNames string `description:"流向区域名称"`
+	Split string `description:"拆分类型"`
+	FlowDirection string `description:"流向,对应periodicity:export/import"`
+	Granularity string `description:"粒度: daily/weekly/monthly/yearly"`
+	Unit string `description:"单位"`
+}
+
+  // withIntraCountry := false
+  // withIntraRegion := true
+  // withForecast := true
+  // withFreightView := false
+  // withProductEstimation := false
+type KplerFlowDataLibReq struct {
+	Products string `description:"产品名称"`
+	FromZones string `description:"来源区域ID,对应Location" ` 
+	ToZones string `description:"流向区域ID"`
+	Split string `description:"拆分类型"`
+	FlowDirection string `description:"流向,对应periodicity:export/import"`
+	Granularity string `description:"粒度: daily/weekly/monthly/yearly"`
+	Unit string `description:"单位"`
+	FromCountries string `description:"来源国家"`
+	ToCountries string `description:"流向国家"`
+	FromInstallations string `description:"来源安装"`
+	ToInstallations string `description:"流向安装"`
+	OnlyRealized string `description:"是否只查询已实现数据"`
+	VesselTypes string `description:"船型"`
+	VesselTypesAlt string `description:"船型"`
+    WithIntraCountry string `description:"是否查询同国数据"`
+    WithIntraRegion string `description:"是否查询同区域数据"`
+    WithForecast string `description:"是否查询预测数据"`
+    WithFreightView string `description:"是否查询运费数据"`
+    WithProductEstimation string `description:"是否查询产品估算数据"`
+    StartDate string `description:"开始日期"`
+    EndDate string `description:"结束日期"`
+}
+
+
+type KplerFlowDataLibResp struct {
+	Ret         int
+	Msg         string
+	ErrMsg      string
+	ErrCode     string
+	Data []KplerFlowData 
+}
+
+type KplerFlowData struct {
+	SplitItem string 
+	IndexData []KplerIndexDataItem 
+}
+
+type KplerIndexItem struct {
+	IndexCode string 
+	IndexName string 
+	Unit string 
+	Frequency string 
+	IndexData []KplerIndexDataItem 
+}
+
+type KplerIndexDataItem struct {
+	DataTime string
+	Value string 
+}
+
+// BaseFromKplerClassify Kpler原始数据分类表
+type BaseFromKplerClassify struct {
+	ClassifyId      int       `orm:"column(classify_id);pk" gorm:"primaryKey"`
+	ClassifyName    string    `description:"分类名称"`
+	ParentId        int       `description:"父级id"`
+	SysUserId       int       `description:"创建人id"`
+	SysUserRealName string    `description:"创建人姓名"`
+	Level           int       `description:"层级"`
+	Sort            int       `description:"排序字段,越小越靠前,默认值:10"`
+	ModifyTime      time.Time `description:"修改时间"`
+	CreateTime      time.Time `description:"创建时间"`
+	ClassifyNameEn  string    `description:"英文分类名称"`
+	ProductId       int       `description:"产品ID"`
+	ProductName     string    `description:"产品名称"`
+	AncestorFamilyId        int       `description:"父级产品ID"`
+	AncestorFamilyName      string    `description:"父级产品名称"`
+	AncestorGroupId         int       `description:"父级产品ID"`
+	AncestorGroupName       string    `description:"父级产品名称"`
+	AncestorProductId       int       `description:"父级产品ID"`
+	AncestorProductName     string    `description:"父级产品名称"`
+	AncestorGradeId         int       `description:"父级产品ID"`
+	AncestorGradeName       string    `description:"父级产品名称"`
+	ClassifyType    string    `description:"分类类型"`
+}
+
+func GetAllBaseFromKplerClassify() (items []*BaseFromKplerClassify, err error) {
+	sql := ` SELECT * FROM base_from_kpler_classify `
+	err = global.DEFAULT_DB.Raw(sql).Find(&items).Error
+	return
+}
+
+// 获取分类
+func (y *BaseFromKplerClassify) GetByProductIds(productIds []int) (items []*BaseFromKplerClassify, err error) {
+	sql := ` SELECT * FROM base_from_kpler_classify WHERE product_id in (?) `
+	err = global.DEFAULT_DB.Raw(sql, productIds).Find(&items).Error
+	return
+}
+
+
+// 获取区域
+// BaseFromKplerZone Kpler区域表
+type BaseFromKplerZone struct {
+	BaseFromKplerZoneId int       `orm:"column(base_from_kpler_zone_id);pk" gorm:"primaryKey"`
+	ZoneName            string    `description:"区域名称"`
+	ZoneType            string    `description:"区域类型"`
+	ParentId            int       `description:"区域父ID"`
+	AncestorId          int       `description:"区域祖先ID"`
+	AncestorType        string    `description:"区域祖先类型"`
+	AncestorName        string    `description:"区域祖先名称"`
+	DescendantId        int       `description:"区域子ID"`
+	DescendantName      string    `description:"区域子名称"`
+	CreateTime          time.Time `description:"创建时间"`
+	ModifyTime          time.Time `description:"修改时间"`
+} 
+
+// 获取区域
+func (y *BaseFromKplerZone) GetByZoneIds(zoneIds []int) (items []*BaseFromKplerZone, err error) {
+	sql := ` SELECT * FROM base_from_kpler_zone WHERE base_from_kpler_zone_id in (?) `
+	err = global.DEFAULT_DB.Raw(sql, zoneIds).Find(&items).Error
+	return
+}
+
+func (y *BaseFromKplerZone) Add() (lastId int64, err error) {
+	err = global.DEFAULT_DB.Create(&y).Error
+	if err != nil {
+		return
+	}
+	lastId = int64(y.BaseFromKplerZoneId)
+	return
+}
+
+type KplerProductLibResp struct {
+	Ret         int
+	Msg         string
+	ErrMsg      string
+	ErrCode     string
+	Data []KplerProduct 
+}
+
+//bodystr := "Id (Product);Name;Type (Product);Family;Family Id;Group;Group Id;Product;Product Id;Grade;Grade Id;Density (Product);Density Unit;Energy Density;Energy Density Unit;Expansion Ratio
+type KplerProduct struct {
+	Id string
+	Name string
+	Type string
+	Family string
+	FamilyId string
+	Group string
+	GroupId string
+	Product string
+	ProductId string
+	Grade string
+	GradeId string
+	Density string
+	DensityUnit string
+	EnergyDensity string
+	EnergyDensityUnit string
+	ExpansionRatio string
+}
+
+type KplerZoneLibResp struct {
+	Ret         int
+	Msg         string
+	ErrMsg      string
+	ErrCode     string
+	Data []KplerZone 
+}
+
+// Ancestor Id;Ancestor Name;Ancestor Type;Descendant Id;Descendant Name;Descendant Type
+type KplerZone struct {
+	AncestorId string
+	AncestorName string
+	AncestorType string
+	DescendantId string
+	DescendantName string
+}
+
+type KplerZoneDataLibReq struct {
+	AncestorName string `description:"祖先名称"`
+	DescendantName string `description:"子名称"`
+}

+ 9 - 0
models/edb_terminal.go

@@ -19,6 +19,7 @@ type EdbTerminal struct {
 	Status       int       `gorm:"column:status;type:tinyint(4);comment:状态,1启用,2禁用;not null;default:1;"`          // 状态,1启用,2禁用
 	Value        string    `gorm:"column:value;type:text;comment:终端相关的凭证;"`                                       // 终端相关的凭证
 	DirPath      string    `gorm:"column:dir_path;type:varchar(255);comment:终端存放的文件夹路径;default:NULL;"`            // 终端存放的文件夹路径
+	IsApi        int       `gorm:"column:is_api;type:tinyint(4);comment:是否为api;default:0;"`                             // 是否为api
 }
 
 // GetEdbTerminalListBySource 根据指标来源类型获取所有的终端列表
@@ -29,6 +30,14 @@ func GetEdbTerminalListBySource(source int) (items []*EdbTerminal, err error) {
 	return
 }
 
+// GetEdbTerminalListBySource 根据指标来源类型获取所有的终端列表
+func GetEdbTerminalListBySourceAndIsApi(source int, isApi int) (items []*EdbTerminal, err error) {
+	sql := ` SELECT *  FROM edb_terminal WHERE source = ? and status=1 and is_api = ? ORDER BY terminal_id ASC `
+	err = global.DEFAULT_DB.Raw(sql, source, isApi).Find(&items).Error
+
+	return
+}
+
 // GetEdbTerminalFirstBySource 根据指标来源类型获取配置的首个终端信息
 func GetEdbTerminalFirstBySource(source int) (item *EdbTerminal, err error) {
 	sql := ` SELECT *  FROM edb_terminal WHERE source = ? and status=1 ORDER BY terminal_id ASC Limit 1 `

+ 45 - 0
routers/commentsRouter.go

@@ -1222,6 +1222,51 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["eta/eta_index_lib/controllers:KplerController"] = append(beego.GlobalControllerRouter["eta/eta_index_lib/controllers:KplerController"],
+        beego.ControllerComments{
+            Method: "Add",
+            Router: `/add`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_index_lib/controllers:KplerController"] = append(beego.GlobalControllerRouter["eta/eta_index_lib/controllers:KplerController"],
+        beego.ControllerComments{
+            Method: "GetData",
+            Router: `/edb_data`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_index_lib/controllers:KplerController"] = append(beego.GlobalControllerRouter["eta/eta_index_lib/controllers:KplerController"],
+        beego.ControllerComments{
+            Method: "HandleExcelData",
+            Router: `/handle/excel_data`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_index_lib/controllers:KplerController"] = append(beego.GlobalControllerRouter["eta/eta_index_lib/controllers:KplerController"],
+        beego.ControllerComments{
+            Method: "IndexAdd",
+            Router: `/index_add`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_index_lib/controllers:KplerController"] = append(beego.GlobalControllerRouter["eta/eta_index_lib/controllers:KplerController"],
+        beego.ControllerComments{
+            Method: "Refresh",
+            Router: `/refresh`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["eta/eta_index_lib/controllers:LtController"] = append(beego.GlobalControllerRouter["eta/eta_index_lib/controllers:LtController"],
         beego.ControllerComments{
             Method: "Add",

+ 5 - 0
routers/router.go

@@ -363,6 +363,11 @@ func init() {
 				&ai_predict_model.AiPredictModelIndexController{},
 			),
 		),
+		beego.NSNamespace("/kpler",
+			beego.NSInclude(
+				&controllers.KplerController{},
+			),
+		),
 	)
 	beego.AddNamespace(ns)
 }

+ 859 - 0
services/base_from_kpler.go

@@ -0,0 +1,859 @@
+package services
+
+import (
+	"encoding/json"
+	"eta/eta_index_lib/logic"
+	"eta/eta_index_lib/models"
+	"eta/eta_index_lib/services/alarm_msg"
+	"eta/eta_index_lib/utils"
+	"fmt"
+	"io/ioutil"
+	"net/http"
+	"strconv"
+	"strings"
+	"time"
+)
+
+// GetKplerDataByApi 获取开普勒数据
+func GetKplerDataByApi(params models.KplerSearchEdbReq, terminalCode string) (indexes []*models.KplerIndexItem, terminalInfo *models.EdbTerminal, err error) {
+	terminal, e := GetApiTerminal(utils.DATA_SOURCE_KPLER, terminalCode)
+	if e != nil {
+		err = fmt.Errorf("获取开普勒终端配置失败, %v", e)
+		return
+	}
+	
+	if terminal.ServerUrl == "" {
+		err = fmt.Errorf("开普勒终端地址未配置")
+		return
+	}
+    
+	// 走API
+	if terminal.IsApi == 1 {
+		indexes, err = getKplerDataByApi(params, terminal.ServerUrl)
+		if err != nil {
+			err = fmt.Errorf("获取开普勒指标数据失败, %v", err)
+			return
+		}
+		terminalInfo = terminal
+		return
+	}
+    return
+}
+
+// getEdbDataFromThsHfHttp API-获取高频指标数据
+func getKplerDataByApi(params models.KplerSearchEdbReq, serverUrl string) (list []*models.KplerIndexItem, err error) {
+	defer func() {
+		if err != nil {
+			tips := fmt.Sprintf("开普勒指标API-getKplerDataByApi err: %v", err)
+			utils.FileLog.Info(tips)
+		}
+	}()
+
+    // todo 判断指标是否已存在
+	productNamesStr := params.ProductNames
+	fromZoneNamesStr := params.FromZoneNames
+	toZoneNamesStr := params.ToZoneNames
+	
+
+	libreq := new(models.KplerFlowDataLibReq)
+	libreq.Products = productNamesStr
+	libreq.FromZones = fromZoneNamesStr
+	libreq.ToZones = toZoneNamesStr
+	libreq.Split = params.Split
+	libreq.FlowDirection = params.FlowDirection
+	libreq.Granularity = params.Granularity
+	libreq.Unit = params.Unit
+	libreq.WithIntraRegion = "true"
+	libreq.WithForecast = "true"
+	libreq.OnlyRealized = "false"
+	libreq.StartDate = "2025-01-01"
+	libreq.EndDate = time.Now().Format(utils.FormatDate)
+	// 请求接口
+	apiResp, err := getKplerFlowDataLib(serverUrl, libreq)
+	if err != nil {
+		err = fmt.Errorf("开普勒指标API-getKplerDataByApi err: %v", err)
+		return
+	}
+	if apiResp.Ret != 200 {
+		err = fmt.Errorf("开普勒指标API-状态码: %d, 提示信息: %s", apiResp.Ret, apiResp.ErrMsg)
+		return
+	}
+	indexes := make([]*models.KplerIndexItem, 0)
+	if len(apiResp.Data) == 0 {
+		utils.FileLog.Info("开普勒指标API-无数据")
+		return
+	}
+    indexCodeList := make([]string, 0)
+	existIndexCodeMap := make(map[string]bool)
+	flowDirection := params.FlowDirection
+	prefixIndexName := fmt.Sprintf("kpler%s%s%s%s", fromZoneNamesStr, flowDirection, toZoneNamesStr, productNamesStr)
+	lastIndexName := params.Granularity
+
+	prefixIndexCode := fmt.Sprintf("k%s%s%s%s", fromZoneNamesStr, flowDirection, toZoneNamesStr, productNamesStr)
+	// 获取首字母
+	lastIndexCode := strings.ToUpper(params.Granularity[:1])
+	// Tables中的每一个对应一个证券代码
+	for _, v := range apiResp.Data {
+			index := new(models.KplerIndexItem)
+			indexName := ""
+			indexCode := ""
+			
+			indexName = fmt.Sprintf("%s%s%s", prefixIndexName, v.SplitItem, lastIndexName)
+			indexCode = fmt.Sprintf("%s%s%s", prefixIndexCode,v.SplitItem, lastIndexCode)
+				
+			indexCodeList = append(indexCodeList, indexCode)
+			index.IndexCode = indexCode
+			index.IndexName = indexName
+			index.Frequency = getKplerFrequency(params.Granularity)
+			index.Unit = params.Unit
+			index.IndexData = v.IndexData
+			indexes = append(indexes, index)
+	}
+
+	indexObj := new(models.BaseFromKplerIndex)
+	// 查询指标是否存在
+	existList, err := indexObj.GetByIndexCodes(indexCodeList)
+	if err != nil {
+		err = fmt.Errorf("查询指标是否存在失败, %v", err)
+		return
+	}
+	for _, v := range existList {
+		existIndexCodeMap[v.IndexCode] = true
+	}
+	// 过滤已经存在的指标
+	list = make([]*models.KplerIndexItem, 0)
+	for _, v := range indexes {
+		if _, ok := existIndexCodeMap[v.IndexCode]; !ok {
+			list = append(list, v)
+		}
+	}
+	return list, nil
+}
+
+func AddKplerIndexByApi(indexList []*models.KplerIndexItem, req *models.KplerSearchEdbReq, classifyId int, terminalCode string) (err error) {
+	errMsgList := make([]string, 0)
+	defer func() {
+		if len(errMsgList) > 0 {
+			msg := fmt.Sprint("数据源-Kpler数据处理失败,err:", strings.Join(errMsgList, "\n"))
+			utils.FileLog.Info(msg)
+			go alarm_msg.SendAlarmMsg(msg, 3)
+		}
+	}()
+	
+	maxSort := 0
+	for _, indexInfo := range indexList {
+		indexObj := new(models.BaseFromKplerIndex)
+		indexId := 0
+		//判断指标是否存在
+		var isAdd int
+		item, er := indexObj.GetByIndexCode(indexInfo.IndexCode)
+	    if er != nil {
+			if er.Error() == utils.ErrNoRow() {
+				isAdd = 1
+				err = nil
+			} else {
+				errMsgList = append(errMsgList, fmt.Sprintf("查询数据源指标库失败 GetByIndexCode Err:%s", er))
+				continue
+			}
+		}
+		if item != nil && item.BaseFromKplerIndexId > 0 {
+			fmt.Println("item:", item)
+			isAdd = 2
+		} else {
+			isAdd = 1
+		}
+		// 批量新增指标
+		if isAdd == 1 {
+			indexObj.IndexCode = indexInfo.IndexCode
+			indexObj.IndexName = indexInfo.IndexName
+			indexObj.Frequency = indexInfo.Frequency
+			indexObj.ClassifyId = int(classifyId)
+			indexObj.ProductNames = req.ProductNames
+			indexObj.FromZoneName = req.FromZoneNames
+			indexObj.ToZoneName = req.ToZoneNames
+			indexObj.FlowDirection = req.FlowDirection
+			indexObj.Granularity = req.Granularity
+			indexObj.Split = req.Split
+			indexObj.Unit = req.Unit
+			indexObj.Sort = maxSort
+			indexObj.ModifyTime = time.Now()
+			indexObj.CreateTime = time.Now()
+			indexObj.TerminalCode = terminalCode
+			err = indexObj.Add()
+			if err != nil {
+				err = fmt.Errorf("数据源新增Kpler指标失败 Err:%s", err)
+				return
+			}
+			indexId = indexObj.BaseFromKplerIndexId
+			maxSort++
+		} else if isAdd == 2 {
+			indexId = item.BaseFromKplerIndexId
+			if item.TerminalCode == `` && terminalCode != `` {
+				item.TerminalCode = terminalCode
+				err = item.Update([]string{"TerminalCode"})
+				if err != nil {
+					err = fmt.Errorf("数据源更新Kpler指标失败 Err:%s", err)
+					return
+				}
+			}
+	
+			indexObj.BaseFromKplerIndexId = item.BaseFromKplerIndexId
+			indexObj.IndexName = indexInfo.IndexName
+			indexObj.Frequency = indexInfo.Frequency
+			indexObj.ClassifyId = int(classifyId)
+			indexObj.ProductNames = req.ProductNames
+			indexObj.FromZoneName = req.FromZoneNames
+			indexObj.ToZoneName = req.ToZoneNames
+			indexObj.FlowDirection = req.FlowDirection
+			indexObj.Granularity = req.Granularity
+			indexObj.Split = req.Split
+			indexObj.Unit = req.Unit
+			indexObj.ModifyTime = time.Now()
+	
+			//修改数据
+			updateColsArr := make([]string, 0)
+			updateColsArr = append(updateColsArr, "index_name")
+			updateColsArr = append(updateColsArr, "classify_id")
+			updateColsArr = append(updateColsArr, "product_names")
+			updateColsArr = append(updateColsArr, "from_zone_name")
+			updateColsArr = append(updateColsArr, "to_zone_name")
+			updateColsArr = append(updateColsArr, "flow_direction")
+			updateColsArr = append(updateColsArr, "granularity")
+			updateColsArr = append(updateColsArr, "split")
+			updateColsArr = append(updateColsArr, "frequency")
+			updateColsArr = append(updateColsArr, "modify_time")
+	
+			e := indexObj.Update(updateColsArr)
+			if e != nil {
+				fmt.Println("Index Update Err:" + e.Error())
+				return
+			}
+		}
+	    dataObj := new(models.BaseFromKplerData)
+		exitDataMap := make(map[string]*models.BaseFromKplerData)
+		//获取已存在的所有数据
+		var exitDataList []*models.BaseFromKplerData
+		exitDataList, err = dataObj.GetByIndexCode(indexInfo.IndexCode)
+		if err != nil {
+			err = fmt.Errorf("数据源查询Kpler指标数据失败 Err:%s", err)
+			return
+		}
+		fmt.Println("exitDataListLen:", len(exitDataList))
+		for _, v := range exitDataList {
+			dateStr := v.DataTime
+			exitDataMap[dateStr] = v
+		}
+		addDataList := make([]*models.BaseFromKplerData, 0)
+	
+		// 遍历excel数据,然后跟现有的数据做校验,不存在则入库
+		for _, value := range indexInfo.IndexData {
+			date := value.DataTime
+			value := value.Value
+			if findData, ok := exitDataMap[date]; !ok {
+				_, err = time.ParseInLocation(utils.FormatDate, date, time.Local)
+				if err != nil {
+					err = fmt.Errorf("%s 转换日期格式失败 Err:%s", date, err)
+					return
+				}
+				var saveDataTime time.Time
+				if strings.Contains(date, "00:00:00") {
+					saveDataTime, err = time.Parse(utils.FormatDateTime, date)
+				} else {
+					saveDataTime, err = time.Parse(utils.FormatDate, date)
+				}
+				if err != nil {
+					err = fmt.Errorf("%s 转换日期格式失败 Err:%s", date, err)
+					continue
+				}
+				timestamp := saveDataTime.UnixNano() / 1e6
+	
+				dataItem := new(models.BaseFromKplerData)
+				dataItem.BaseFromKplerIndexId = int(indexId)
+				dataItem.IndexCode = indexInfo.IndexCode
+				dataItem.DataTime = date
+				dataItem.Value = value
+				dataItem.CreateTime = time.Now()
+				dataItem.ModifyTime = time.Now()
+				dataItem.DataTimestamp = timestamp
+				addDataList = append(addDataList, dataItem)
+				if len(addDataList) > 500 {
+					err = dataObj.AddMulti(addDataList)
+					if err != nil {
+						err = fmt.Errorf("批量新增指标失败 Err:%s", err)
+						return
+					}
+					addDataList = make([]*models.BaseFromKplerData, 0)
+				}
+			} else {
+				if findData != nil && findData.Value != value && !strings.Contains(value, "#N/A") { //修改数据
+					// 过滤0.50和0.5的比较
+					oldV, _ := strconv.ParseFloat(findData.Value, 64)
+					newV, _ := strconv.ParseFloat(value, 64)
+					if oldV == newV {
+						continue
+					}
+					dataObj.BaseFromKplerIndexId = findData.BaseFromKplerIndexId
+					dataObj.Value = value
+					dataObj.ModifyTime = time.Now()
+	
+					updateDataColsArr := make([]string, 0)
+					updateDataColsArr = append(updateDataColsArr, "value")
+					updateDataColsArr = append(updateDataColsArr, "modify_time")
+					dataObj.Update(updateDataColsArr)
+				}
+			}
+		}
+	
+		if len(addDataList) > 0 {
+			err = dataObj.AddMulti(addDataList)
+			if err != nil {
+				err = fmt.Errorf("批量新增指标失败 Err:%s", err)
+				return
+			}
+		}
+	
+		var dateItem *models.EdbInfoMaxAndMinInfo
+		dateItem, err = dataObj.GetMaxAndMinDateByIndexCode(indexInfo.IndexCode)
+		if err != nil {
+			err = fmt.Errorf("查询指标最新日期失败 Err:%s", err)
+			return
+		}
+	
+		go func() {
+			indexObj.ModifyIndexMaxAndMinDate(indexInfo.IndexCode, dateItem)
+		}()
+	
+		// 同步刷新ETA指标库的指标
+		{
+			// 获取指标详情
+			baseObj := new(models.BaseFromKpler)
+			var edbInfo *models.EdbInfo
+			edbInfo, err = models.GetEdbInfoByEdbCode(baseObj.GetSource(), indexInfo.IndexCode)
+			if err != nil {
+				if !utils.IsErrNoRow(err) {
+					errMsgList = append(errMsgList, fmt.Sprint("刷新ETA指标异常,指标编码:", indexInfo.IndexCode, err.Error()))
+					return
+				} else {
+					err = nil
+				}
+			}
+	
+			// 已经加入到指标库的话,那么就去更新ETA指标库吧
+			if edbInfo != nil {
+				go logic.RefreshBaseEdbInfo(edbInfo, ``)
+			}
+		}
+	}
+	return
+}
+
+// HandleKplerIndex 处理Kpler的excel数据
+func HandleKplerIndex(req *models.HandleKplerExcelDataReq) (err error) {
+	errMsgList := make([]string, 0)
+	defer func() {
+		if len(errMsgList) > 0 {
+			msg := fmt.Sprint("数据源-Kpler数据处理失败,err:", strings.Join(errMsgList, "\n"))
+			utils.FileLog.Info(msg)
+			go alarm_msg.SendAlarmMsg(msg, 3)
+		}
+	}()
+	// 查询所有的一级分类
+	classifyObj := new(models.BaseFromKplerClassify)
+	classifyList, err := classifyObj.GetParentClassify()
+	if err != nil {
+		err = fmt.Errorf("查询一级目录信息失败 Err:%s", err)
+		return
+	}
+	classifyMap := make(map[string]int, 0)
+	for _, v := range classifyList {
+		classifyMap[v.ClassifyName] = int(v.ClassifyId)
+	}
+
+	for _, v := range req.List {
+		if v.IndexName == "" || v.IndexCode == "" {
+			errMsgList = append(errMsgList, fmt.Sprintf("新增指标异常,指标编码%s或者指标ID%s为空:", v.IndexCode, v.IndexName))
+			continue
+		}
+		err = handleKplerIndex(v, req.TerminalCode, classifyMap)
+		if err != nil {
+			errMsgList = append(errMsgList, fmt.Sprintf("新增指标异常,指标编码:%s, Err: %s", v.IndexCode, err))
+			return
+		}
+	}
+	return
+}
+
+// getKplerFlowDataLib 获取开普勒流数据
+func getKplerFlowDataLib(libUrl string, dataMap *models.KplerFlowDataLibReq) (resp *models.KplerFlowDataLibResp, err error) {
+	postUrl := fmt.Sprintf("%s%s", libUrl, "/v1/kpler/getFlowData")
+	postData, err := json.Marshal(dataMap)
+	if err != nil {
+		return
+	}
+	result, err := HttpPost(postUrl, string(postData), "application/json")
+	if err != nil {
+		return
+	}
+	utils.FileLog.Info("postRefreshEdbData:" + postUrl + ";" + string(postData) + ";result:" + string(result))
+	err = json.Unmarshal(result, &resp)
+	if err != nil {
+		return
+	}
+	return resp, nil
+}
+
+func getKplerProductLib(libUrl string) (resp *models.KplerProductLibResp, err error) {
+	postUrl := fmt.Sprintf("%s%s", libUrl, "/v1/kpler/getProductData")
+	result, err := HttpPost(postUrl, "", "application/json")
+	if err != nil {
+		return
+	}
+	utils.FileLog.Info("postRefreshEdbData:" + postUrl + ";result:" + string(result))
+	err = json.Unmarshal(result, &resp)
+	if err != nil {
+		return
+	}
+	return resp, nil
+}
+
+func getKplerZoneLib(libUrl string) (resp *models.KplerZoneLibResp, err error) {
+	postUrl := fmt.Sprintf("%s%s", libUrl, "/v1/kpler/getZoneData")
+	result, err := HttpPost(postUrl, "", "application/json")
+	if err != nil {
+		return
+	}
+	utils.FileLog.Info("postRefreshEdbData:" + postUrl + ";result:" + string(result))
+	err = json.Unmarshal(result, &resp)
+	if err != nil {
+		return
+	}
+	return resp, nil
+}
+
+func handleKplerIndex(req *models.HandleKplerExcelData, terminalCode string, classifyMap map[string]int) (err error) {
+	indexName := req.IndexName
+	indexCode := req.IndexCode
+	excelDataMap := req.ExcelDataMap
+	errMsgList := make([]string, 0)
+	defer func() {
+		if len(errMsgList) > 0 {
+			msg := fmt.Sprint("数据源-Kpler数据处理失败,err:", strings.Join(errMsgList, "\n"))
+			utils.FileLog.Info(msg)
+			go alarm_msg.SendAlarmMsg(msg, 3)
+		}
+	}()
+	indexObj := new(models.BaseFromKplerIndex)
+	dataObj := new(models.BaseFromKplerData)
+	classifyObj := new(models.BaseFromKplerClassify)
+
+	var indexId int64
+
+	addDataList := make([]*models.BaseFromKplerData, 0)
+
+	exitDataMap := make(map[string]*models.BaseFromKplerData)
+
+	// 修改指标信息
+	if indexName == "" {
+		utils.FileLog.Info("未刷新到指标数据:indexName:" + indexName)
+		return
+	}
+	// 判断目录是否存在
+	var classifyId int64
+	now := time.Now()
+	if req.ClassifyName != "" {
+		classifyParentId := 0
+		level := 1
+		classifyParentId, _ = classifyMap[req.ParentClassifyName]
+		if classifyParentId > 0 {
+			level = 2
+		}
+		classifyObj, err = classifyObj.GetByClassifyName(req.ClassifyName)
+		if err != nil {
+			if err.Error() == utils.ErrNoRow() {
+				//新增分类
+				classifyObj = &models.BaseFromKplerClassify{
+					ClassifyName:    req.ClassifyName,
+					ClassifyNameEn:  req.ClassifyName,
+					ParentId:        classifyParentId,
+					SysUserId:       0,
+					SysUserRealName: "",
+					Level:           level,
+					Sort:            req.ClassifySort,
+					ModifyTime:      now,
+					CreateTime:      now,
+				}
+
+				classifyId, err = classifyObj.Add()
+				if err != nil {
+					err = fmt.Errorf("新增分类失败 Err:%s", err)
+					return
+				}
+				classifyObj.ClassifyId = int(classifyId)
+			} else {
+				return
+			}
+		} else {
+			classifyId = int64(classifyObj.ClassifyId)
+			classifyObj.ModifyTime = now
+			classifyObj.ParentId = classifyParentId
+			e := classifyObj.Update([]string{"ParentId", "ModifyTime"})
+			if e != nil {
+				fmt.Println("classifyObj Update Err:" + e.Error())
+				return
+			}
+		}
+	}
+
+	//判断指标是否存在
+	var isAdd int
+	item, err := indexObj.GetByIndexCode(indexCode)
+	if err != nil {
+		if err.Error() == utils.ErrNoRow() {
+			isAdd = 1
+			err = nil
+		} else {
+			isAdd = -1
+			err = fmt.Errorf("查询数据源指标库失败 GetByIndexCode Err:%s", err)
+			return
+		}
+	}
+	if item != nil && item.BaseFromKplerIndexId > 0 {
+		fmt.Println("item:", item)
+		isAdd = 2
+	} else {
+		isAdd = 1
+	}
+
+	if isAdd == 1 {
+		indexObj.IndexCode = indexCode
+		indexObj.IndexName = indexName
+		indexObj.Frequency = req.Frequency
+		indexObj.ClassifyId = int(classifyId)
+		indexObj.ProductNames = req.ProductNames
+		indexObj.FromZoneId = req.FromZoneId
+		indexObj.FromZoneName = req.FromZoneName
+		indexObj.ToZoneId = req.ToZoneId
+		indexObj.ToZoneName = req.ToZoneName
+		indexObj.FlowDirection = req.FlowDirection
+		indexObj.Granularity = req.Granularity
+		indexObj.Split = req.Split
+		indexObj.Unit = req.Unit
+		indexObj.Sort = req.Sort
+		indexObj.ModifyTime = time.Now()
+		indexObj.CreateTime = time.Now()
+		indexObj.TerminalCode = terminalCode
+		err = indexObj.Add()
+		if err != nil {
+			err = fmt.Errorf("数据源新增Kpler指标失败 Err:%s", err)
+			return
+		}
+		indexId = int64(indexObj.BaseFromKplerIndexId)
+	} else if isAdd == 2 {
+		indexId = int64(item.BaseFromKplerIndexId)
+		if item.TerminalCode == `` && terminalCode != `` {
+			item.TerminalCode = terminalCode
+			err = item.Update([]string{"TerminalCode"})
+			if err != nil {
+				err = fmt.Errorf("数据源更新Kpler指标失败 Err:%s", err)
+				return
+			}
+		}
+
+		indexObj.BaseFromKplerIndexId = item.BaseFromKplerIndexId
+		indexObj.IndexName = indexName
+		indexObj.Frequency = req.Frequency
+		indexObj.ClassifyId = int(classifyId)
+		indexObj.ProductNames = req.ProductNames
+		indexObj.FromZoneId = req.FromZoneId
+		indexObj.FromZoneName = req.FromZoneName
+		indexObj.ToZoneId = req.ToZoneId
+		indexObj.ToZoneName = req.ToZoneName
+		indexObj.FlowDirection = req.FlowDirection
+		indexObj.Granularity = req.Granularity
+		indexObj.Split = req.Split
+		indexObj.Unit = req.Unit
+		indexObj.Sort = req.Sort
+		indexObj.ModifyTime = time.Now()
+
+		//修改数据
+		updateColsArr := make([]string, 0)
+		updateColsArr = append(updateColsArr, "index_name")
+		updateColsArr = append(updateColsArr, "classify_id")
+		updateColsArr = append(updateColsArr, "product_names")
+		updateColsArr = append(updateColsArr, "from_zone_id")
+		updateColsArr = append(updateColsArr, "from_zone_name")
+		updateColsArr = append(updateColsArr, "to_zone_id")
+		updateColsArr = append(updateColsArr, "to_zone_name")
+		updateColsArr = append(updateColsArr, "flow_direction")
+		updateColsArr = append(updateColsArr, "granularity")
+		updateColsArr = append(updateColsArr, "split")
+		updateColsArr = append(updateColsArr, "frequency")
+		updateColsArr = append(updateColsArr, "sort")
+		updateColsArr = append(updateColsArr, "modify_time")
+
+		e := indexObj.Update(updateColsArr)
+		if e != nil {
+			fmt.Println("Index Update Err:" + e.Error())
+			return
+		}
+	}
+
+	//获取已存在的所有数据
+	var exitDataList []*models.BaseFromKplerData
+	exitDataList, err = dataObj.GetByIndexCode(indexCode)
+	if err != nil {
+		err = fmt.Errorf("数据源查询Kpler指标数据失败 Err:%s", err)
+		return
+	}
+	fmt.Println("exitDataListLen:", len(exitDataList))
+	for _, v := range exitDataList {
+		dateStr := v.DataTime
+		exitDataMap[dateStr] = v
+	}
+
+	// 遍历excel数据,然后跟现有的数据做校验,不存在则入库
+	for date, value := range excelDataMap {
+		if findData, ok := exitDataMap[date]; !ok {
+			_, err = time.ParseInLocation(utils.FormatDate, date, time.Local)
+			if err != nil {
+				err = fmt.Errorf("%s 转换日期格式失败 Err:%s", date, err)
+				return
+			}
+			var saveDataTime time.Time
+			if strings.Contains(date, "00:00:00") {
+				saveDataTime, err = time.Parse(utils.FormatDateTime, date)
+			} else {
+				saveDataTime, err = time.Parse(utils.FormatDate, date)
+			}
+			if err != nil {
+				err = fmt.Errorf("%s 转换日期格式失败 Err:%s", date, err)
+				continue
+			}
+			timestamp := saveDataTime.UnixNano() / 1e6
+
+			dataItem := new(models.BaseFromKplerData)
+			dataItem.BaseFromKplerIndexId = int(indexId)
+			dataItem.IndexCode = indexCode
+			dataItem.DataTime = date
+			dataItem.Value = value
+			dataItem.CreateTime = time.Now()
+			dataItem.ModifyTime = time.Now()
+			dataItem.DataTimestamp = timestamp
+			addDataList = append(addDataList, dataItem)
+			if len(addDataList) > 500 {
+				err = dataObj.AddMulti(addDataList)
+				if err != nil {
+					err = fmt.Errorf("批量新增指标失败 Err:%s", err)
+					return
+				}
+				addDataList = make([]*models.BaseFromKplerData, 0)
+			}
+		} else {
+			if findData != nil && findData.Value != value && !strings.Contains(value, "#N/A") { //修改数据
+				// 过滤0.50和0.5的比较
+				oldV, _ := strconv.ParseFloat(findData.Value, 64)
+				newV, _ := strconv.ParseFloat(value, 64)
+				if oldV == newV {
+					continue
+				}
+				dataObj.BaseFromKplerIndexId = findData.BaseFromKplerIndexId
+				dataObj.Value = value
+				dataObj.ModifyTime = time.Now()
+
+				updateDataColsArr := make([]string, 0)
+				updateDataColsArr = append(updateDataColsArr, "value")
+				updateDataColsArr = append(updateDataColsArr, "modify_time")
+				dataObj.Update(updateDataColsArr)
+			}
+		}
+	}
+
+	if len(addDataList) > 0 {
+		err = dataObj.AddMulti(addDataList)
+		if err != nil {
+			err = fmt.Errorf("批量新增指标失败 Err:%s", err)
+			return
+		}
+	}
+
+	var dateItem *models.EdbInfoMaxAndMinInfo
+	dateItem, err = dataObj.GetMaxAndMinDateByIndexCode(indexCode)
+	if err != nil {
+		err = fmt.Errorf("查询指标最新日期失败 Err:%s", err)
+		return
+	}
+
+	go func() {
+		indexObj.ModifyIndexMaxAndMinDate(indexCode, dateItem)
+	}()
+
+	// 同步刷新ETA指标库的指标
+	{
+		// 获取指标详情
+		baseObj := new(models.BaseFromKpler)
+		var edbInfo *models.EdbInfo
+		edbInfo, err = models.GetEdbInfoByEdbCode(baseObj.GetSource(), indexCode)
+		if err != nil {
+			if !utils.IsErrNoRow(err) {
+				errMsgList = append(errMsgList, fmt.Sprint("刷新ETA指标异常,指标编码:", indexCode, err.Error()))
+				return
+			} else {
+				err = nil
+			}
+		}
+
+		// 已经加入到指标库的话,那么就去更新ETA指标库吧
+		if edbInfo != nil {
+			go logic.RefreshBaseEdbInfo(edbInfo, ``)
+		}
+	}
+	return
+} 
+
+func HttpPost(url, postData string, params ...string) ([]byte, error) {
+	body := ioutil.NopCloser(strings.NewReader(postData))
+	client := &http.Client{}
+	req, err := http.NewRequest("POST", url, body)
+	if err != nil {
+		return nil, err
+	}
+	contentType := "application/x-www-form-urlencoded;charset=utf-8"
+	if len(params) > 0 && params[0] != "" {
+		contentType = params[0]
+	}
+	req.Header.Set("Content-Type", contentType)
+	req.Header.Set("authorization", utils.MD5(utils.APP_EDB_DATA_ANALYSIS+utils.EDB_DATA_ANALYSIS_Md5_KEY))
+	resp, err := client.Do(req)
+	if err != nil {
+		return nil, err
+	}
+	defer resp.Body.Close()
+	b, err := ioutil.ReadAll(resp.Body)
+	utils.FileLog.Debug("HttpPost:" + string(b))
+	return b, err
+}
+
+func getKplerFrequency(granularity string) (frequency string) {
+	switch granularity {
+	case "daily":
+		return "日度"
+	case "weekly":
+		return "周度"
+	case "monthly":
+		return "月度"
+	case "yearly":
+		return "年度"
+	}
+	return ""
+}
+
+
+func InitKplerProduct ()(err error) {
+	libUrl := "http://127.0.0.1:8915"
+	libResp, err := getKplerProductLib(libUrl)
+	if err != nil {
+		return
+	}
+	if libResp.Ret != 200 {
+		fmt.Println("获取开普勒产品库失败", libResp.ErrMsg)
+		utils.FileLog.Info("获取开普勒产品库失败", libResp.ErrMsg)
+		return
+	}
+	classifyList, err := models.GetAllBaseFromKplerClassify()
+	if err != nil {
+		return
+	}
+	classifyMap := make(map[int]*models.BaseFromKplerClassify)
+	for _, v := range classifyList {
+		classifyMap[v.ProductId] = v
+	}
+	// 批量插入分类表中
+	// family > group(commodity) >  product() > grade
+	sort := 0
+	for _, v := range libResp.Data {
+		id, _ := strconv.Atoi(v.Id)
+		if classifyObj, ok := classifyMap[id]; !ok {
+		    classifyObj = new(models.BaseFromKplerClassify)
+		    classifyObj.ClassifyName = v.Name
+		    classifyObj.ClassifyNameEn = v.Name
+			classifyObj.ModifyTime = time.Now()
+			classifyObj.CreateTime = time.Now()
+			classifyObj.Sort = sort
+			classifyObj.Level = 1
+			classifyObj.ParentId = 0
+			classifyObj.SysUserId = 0
+			classifyObj.SysUserRealName = ""
+			classifyObj.ProductId = id
+			classifyObj.ProductName = v.Name
+			classifyObj.AncestorFamilyId, _ = strconv.Atoi(v.FamilyId)
+			classifyObj.AncestorFamilyName = v.Family
+			classifyObj.AncestorGroupId, _ = strconv.Atoi(v.GroupId)
+			classifyObj.AncestorGroupName = v.Group
+			classifyObj.AncestorProductId, _ = strconv.Atoi(v.ProductId)
+			classifyObj.AncestorProductName = v.Product
+			classifyObj.AncestorGradeId, _ = strconv.Atoi(v.GradeId)
+			classifyObj.AncestorGradeName = v.Grade
+			classifyObj.ClassifyType = v.Type
+			_, err = classifyObj.Add()
+			if err != nil {
+				fmt.Println("新增开普勒产品库失败", err)
+				utils.FileLog.Info("新增开普勒产品库失败", err)
+			}
+			classifyMap[id] = classifyObj
+		}
+	}
+	
+    for _, v := range classifyMap {
+		if v.ParentId == 0 {
+			if v.AncestorGradeId > 0 && v.AncestorGradeName != v.ClassifyName {
+				v.ParentId = classifyMap[v.AncestorGradeId].ClassifyId
+			} else if v.AncestorProductId > 0 && v.AncestorProductName != v.ClassifyName {
+				v.ParentId = classifyMap[v.AncestorProductId].ClassifyId
+			} else if v.AncestorGroupId > 0 && v.AncestorGroupName != v.ClassifyName {
+				v.ParentId = classifyMap[v.AncestorGroupId].ClassifyId
+			}
+			err = v.Update([]string{"ParentId"})
+			if err != nil {
+				fmt.Println("更新开普勒产品库失败", err)
+				utils.FileLog.Info("更新开普勒产品库失败", err)
+			}
+		}
+	}
+	
+	fmt.Println("classifyList:", classifyList)
+	return
+}
+
+
+func InitKplerZone() (err error) {
+	libUrl := "http://127.0.0.1:8915"
+	libResp, err := getKplerZoneLib(libUrl)
+	if err != nil {
+		return
+	}
+	if libResp.Ret != 200 {
+		fmt.Println("获取开普勒区域库失败", libResp.ErrMsg)
+		utils.FileLog.Info("获取开普勒区域库失败", libResp.ErrMsg)
+		return
+	}
+
+	// 批量插入区域表中
+	for _, v := range libResp.Data {
+		zoneObj := new(models.BaseFromKplerZone)
+		zoneObj.ZoneName = v.AncestorName
+		zoneObj.ZoneType = v.AncestorType
+		zoneObj.AncestorId, _ = strconv.Atoi(v.AncestorId)
+		zoneObj.AncestorType = v.AncestorType
+		zoneObj.AncestorName = v.AncestorName
+		zoneObj.DescendantId, _ = strconv.Atoi(v.DescendantId)
+		zoneObj.DescendantName = v.DescendantName
+		zoneObj.ModifyTime = time.Now()
+		zoneObj.CreateTime = time.Now()
+		_, err = zoneObj.Add()
+		if err != nil {
+			fmt.Println("新增开普勒区域库失败", err)
+			utils.FileLog.Info("新增开普勒区域库失败", err)
+		}
+	}
+	return
+}

+ 52 - 4
services/edb_terminal.go

@@ -65,10 +65,58 @@ func GetTerminal(source int, oldTerminalCode string) (edbTerminal *models.EdbTer
 		err = errors.New("获取配置的终端地址失败")
 		return
 	}
-	/*if edbTerminal != nil {
-		windUrl = edbTerminal.ServerUrl
-		terminalCode = edbTerminal.TerminalCode
-	}*/
+	return
+}
+
+func GetApiTerminal(source int, oldTerminalCode string) (edbTerminal *models.EdbTerminal, err error) {
+	if oldTerminalCode != "" {
+		edbTerminal, err = models.GetEdbTerminalByCode(oldTerminalCode)
+		if err != nil {
+			return
+		}
+		if edbTerminal.IsApi == 0 {
+			err = errors.New("终端地址未配置")
+			return
+		}
+		return
+	}
+
+	// 配置中没有的话,那么就从分组获取,
+	list, err := models.GetEdbCountGroupByTerminal(source)
+	if err != nil {
+		return
+	}
+	//windUrlNum := 0
+
+	//获取对应的配置url
+	terminalNumMap := make(map[string]int)
+	for _, v := range list {
+		terminalNumMap[v.TerminalCode] = v.Total
+	}
+
+	terminalList, err := models.GetEdbTerminalListBySourceAndIsApi(source, 1)
+	if err != nil {
+		return
+	}
+	if len(terminalList) == 0 {
+		err = errors.New("终端地址未配置")
+		return
+	}
+	num := 0
+	for _, v := range terminalList {
+		tmpNum := terminalNumMap[v.TerminalCode]
+		if edbTerminal == nil {
+			edbTerminal = v
+			num = tmpNum
+		} else if tmpNum < num {
+			edbTerminal = v
+			num = tmpNum
+		}
+	}
+	if edbTerminal == nil {
+		err = errors.New("获取配置的终端地址失败")
+		return
+	}
 	return
 }
 

+ 11 - 0
utils/config.go

@@ -118,6 +118,11 @@ var (
 	SmmDataMethod string // Smm有色指标数据获取方式
 )
 
+var (
+	APP_EDB_DATA_ANALYSIS string // 公用机数据解析服务
+	EDB_DATA_ANALYSIS_Md5_KEY string // 公用机数据解析服务Md5密钥
+)
+
 func init() {
 	tmpRunMode, err := web.AppConfig.String("run_mode")
 	if err != nil {
@@ -270,6 +275,12 @@ func init() {
 		LogMaxDays, _ = strconv.Atoi(logMaxDaysStr)
 	}
 
+	// 公用机数据解析服务
+	{
+		APP_EDB_DATA_ANALYSIS = config["app_edb_data_analysis"]
+		EDB_DATA_ANALYSIS_Md5_KEY = config["edb_data_analysis_md5_key"]
+	}
+
 	// 数据指标库ES索引名称
 	InitAdminId = config["init_admin_id"]
 

+ 2 - 0
utils/constants.go

@@ -127,6 +127,7 @@ const (
 	DATA_SOURCE_GPR_RISK                             = 102
 	DATA_SOURCE_PuRang                               = 104 // 普兰金融-> 104
 	DATA_SOURCE_RADISH_RESEARCH                      = 105 // 萝卜投研
+	DATA_SOURCE_KPLER                                = 106 // 开普勒 -> 106
 )
 
 // 指标来源的中文展示
@@ -223,6 +224,7 @@ const (
 	DATA_SOURCE_NAME_GPR_RISK                             = `GPR地缘风险指数` // GPR地缘风险指数 -> 102
 	DATA_SOURCE_NAME_PuRang                               = `普兰金融`      // 普兰金融 -> 104
 	DATA_SOURCE_NAME_RADISH_RESEARCH                      = `萝卜投研`      // 萝卜投研 -> 105
+	DATA_SOURCE_NAME_KPLER                                = `Kpler`      // 开普勒 -> 106
 )
 
 // 基础数据初始化日期