Browse Source

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

# Conflicts:
#	routers/router.go
xyxie 1 ngày trước cách đây
mục cha
commit
6e74bb1932

+ 1490 - 0
controllers/data_manage/kpler_data.go

@@ -0,0 +1,1490 @@
+package data_manage
+
+import (
+	"encoding/json"
+	"eta/eta_api/controllers"
+	"eta/eta_api/models"
+	"eta/eta_api/models/data_manage"
+	"eta/eta_api/models/system"
+	"eta/eta_api/services/data"
+	etaTrialService "eta/eta_api/services/eta_trial"
+	"eta/eta_api/utils"
+	"fmt"
+	"os"
+	"path/filepath"
+	"sort"
+	"strconv"
+	"strings"
+	"time"
+
+	"github.com/rdlucklib/rdluck_tools/paging"
+	"github.com/tealeg/xlsx"
+)
+
+type BaseFromKplerController struct {
+	controllers.BaseAuthController
+}
+
+
+// Search
+// @Title 新增指标-查询指标信息接口
+// @Description 新增指标-查询指标信息接口
+// @Param	request	body data_manage.ThsHfSearchEdbReq true "type json string"
+// @Success 200 {object} data_manage.ThsHfSearchEdbResp
+// @router /kpler/index/search [post]
+func (this *BaseFromKplerController) Search() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	var params data_manage.KplerSearchReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &params); e != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + e.Error()
+		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
+	}
+	var productNamesStr string
+	var fromZoneNamesStr string
+	var toZoneNamesStr string
+	if len(params.ProductIds) > 0 {
+		// 获取产品名称
+		productList, e := data_manage.GetKplerClassifyByProductId(params.ProductIds)
+	    if e != nil {
+			br.Msg = "获取Kpler产品名称失败"
+			br.ErrMsg = fmt.Sprintf("获取Kpler产品名称失败, %v", e)
+			return
+		}
+		productNames := make([]string, 0)
+		for _, v := range productList {
+			productNames = append(productNames, v.ProductName)
+		}
+		if len(productNames) > 0 {
+			productNamesStr = strings.Join(productNames, ",")
+		}
+	}
+	// 获取区域名称
+	zoneObj := new(data_manage.BaseFromKplerZone)
+	if len(params.FromZoneIds) > 0 {
+		fromZoneList, e := zoneObj.GetByZoneIds(params.FromZoneIds)
+		if e != nil {
+			br.Msg = "获取Kpler区域名称失败"
+			br.ErrMsg = fmt.Sprintf("获取Kpler区域名称失败, %v", e)
+			return
+		}
+		fromZoneNames := make([]string, 0)
+		for _, v := range fromZoneList {
+			fromZoneNames = append(fromZoneNames, v.ZoneName)
+		}
+		if len(fromZoneNames) > 0 {
+			fromZoneNamesStr = strings.Join(fromZoneNames, ",")
+		}
+	}
+	if len(params.ToZoneIds) > 0 {
+		toZoneList, e := zoneObj.GetByZoneIds(params.ToZoneIds)
+		if e != nil {
+			br.Msg = "获取Kpler区域名称失败"
+			br.ErrMsg = fmt.Sprintf("获取Kpler区域名称失败, %v", e)
+			return
+		}
+		toZoneNames := make([]string, 0)
+		for _, v := range toZoneList {
+			toZoneNames = append(toZoneNames, v.ZoneName)
+		}
+		if len(toZoneNames) > 0 {
+			toZoneNamesStr = strings.Join(toZoneNames, ",")
+		}
+	}
+
+	
+    
+	// 校验已入库的指标
+	if params.Split == "Total" {
+	    flowDirection := params.FlowDirection
+	    // prefixIndexName := fmt.Sprintf("kpler%s%s%s%s", fromZoneNamesStr, flowDirection, toZoneNamesStr, productNamesStr)
+	    // lastIndexName := params.Granularity
+		// indexName := fmt.Sprintf("%s%s%s", prefixIndexName, "Total", lastIndexName)
+	    prefixIndexCode := fmt.Sprintf("k%s%s%s%s", fromZoneNamesStr, flowDirection, toZoneNamesStr, productNamesStr)
+	    // 获取首字母
+	    lastIndexCode := strings.ToUpper(params.Granularity[:1]) 
+		indexCode := fmt.Sprintf("%s%s%s", prefixIndexCode, "Total", lastIndexCode)
+	    // 查询指标是否已存在
+		_, e := data_manage.GetKplerIndexByIndexCode(indexCode)
+		if e != nil && !utils.IsErrNoRow(e) {
+			br.Msg = "获取指标信息失败"
+			br.ErrMsg = fmt.Sprintf("获取指标信息失败, %v", e)
+			return
+		}
+		if e == nil {
+			br.Msg = "指标均已存在"
+		    return
+		}
+	}
+	
+
+	resp := make([]*data_manage.KplerIndexItem, 0)
+
+	// 请求API获取数据
+	indexes, e := data.GetEdbDataKpler(params, productNamesStr, fromZoneNamesStr, toZoneNamesStr)
+	if e != nil {
+		br.Msg = "未搜索到指标"
+		br.ErrMsg = fmt.Sprintf("获取指标失败, %v", e)
+		return
+	}
+	if len(indexes) == 0 {
+		br.Msg = "未搜索到指标"
+		return
+	}
+	for _, v := range indexes {
+		item := new(data_manage.KplerIndexItem)
+		item.IndexCode = v.IndexCode
+		item.IndexName = v.IndexName
+		item.Frequency = v.Frequency
+		item.Unit = v.Unit
+
+		// 搜索只展示100条数据
+		var limit int
+		sort.Slice(v.IndexData, func(i, j int) bool {
+			return v.IndexData[i].DataTime < v.IndexData[j].DataTime
+		})
+		for _, d := range v.IndexData {
+			if limit > 100 {
+				break
+			}
+			limit += 1
+			item.IndexData = append(item.IndexData, d)
+		}
+		resp = append(resp, item)
+	}
+
+	br.Data = resp
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+}
+
+// IndexAdd
+// @Title 新增指标-新增指标接口
+// @Description 新增指标-新增指标接口
+// @Param	request	body data_manage.ThsHfSearchEdbReq true "type json string"
+// @Success 200 {object} data_manage.ThsHfSearchEdbResp
+// @router /kpler/index/add [post]
+func (this *BaseFromKplerController) IndexAdd() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	var params data_manage.KplerSearchReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &params); e != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + e.Error()
+		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
+	}
+	var productNamesStr string
+	var fromZoneNamesStr string
+	var toZoneNamesStr string
+	if len(params.ProductIds) > 0 {
+		// 获取产品名称
+		productList, e := data_manage.GetKplerClassifyByProductId(params.ProductIds)
+	    if e != nil {
+			br.Msg = "获取Kpler产品名称失败"
+			br.ErrMsg = fmt.Sprintf("获取Kpler产品名称失败, %v", e)
+			return
+		}
+		productNames := make([]string, 0)
+		for _, v := range productList {
+			productNames = append(productNames, v.ProductName)
+		}
+		if len(productNames) > 0 {
+			productNamesStr = strings.Join(productNames, ",")
+		}
+	}
+	// 获取区域名称
+	zoneObj := new(data_manage.BaseFromKplerZone)
+	if len(params.FromZoneIds) > 0 {
+		fromZoneList, e := zoneObj.GetByZoneIds(params.FromZoneIds)
+		if e != nil {
+			br.Msg = "获取Kpler区域名称失败"
+			br.ErrMsg = fmt.Sprintf("获取Kpler区域名称失败, %v", e)
+			return
+		}
+		fromZoneNames := make([]string, 0)
+		for _, v := range fromZoneList {
+			fromZoneNames = append(fromZoneNames, v.ZoneName)
+		}
+		if len(fromZoneNames) > 0 {
+			fromZoneNamesStr = strings.Join(fromZoneNames, ",")
+		}
+	}
+	if len(params.ToZoneIds) > 0 {
+		toZoneList, e := zoneObj.GetByZoneIds(params.ToZoneIds)
+		if e != nil {
+			br.Msg = "获取Kpler区域名称失败"
+			br.ErrMsg = fmt.Sprintf("获取Kpler区域名称失败, %v", e)
+			return
+		}
+		toZoneNames := make([]string, 0)
+		for _, v := range toZoneList {
+			toZoneNames = append(toZoneNames, v.ZoneName)
+		}
+		if len(toZoneNames) > 0 {
+			toZoneNamesStr = strings.Join(toZoneNames, ",")
+		}
+	}
+
+	
+    
+	// 校验已入库的指标
+	if params.Split == "Total" {
+	    flowDirection := params.FlowDirection
+	    // prefixIndexName := fmt.Sprintf("kpler%s%s%s%s", fromZoneNamesStr, flowDirection, toZoneNamesStr, productNamesStr)
+	    // lastIndexName := params.Granularity
+		// indexName := fmt.Sprintf("%s%s%s", prefixIndexName, "Total", lastIndexName)
+	    prefixIndexCode := fmt.Sprintf("k%s%s%s%s", fromZoneNamesStr, flowDirection, toZoneNamesStr, productNamesStr)
+	    // 获取首字母
+	    lastIndexCode := strings.ToUpper(params.Granularity[:1]) 
+		indexCode := fmt.Sprintf("%s%s%s", prefixIndexCode, "T", lastIndexCode)
+	    // 查询指标是否已存在
+		_, e := data_manage.GetKplerIndexByIndexCode(indexCode)
+		if e != nil && !utils.IsErrNoRow(e) {
+			br.Msg = "获取指标信息失败"
+			br.ErrMsg = fmt.Sprintf("获取指标信息失败, %v", e)
+			return
+		}
+		if e == nil {
+			br.Msg = "指标均已存在"
+		    return
+		}
+	}
+	
+
+	resp := make([]*data_manage.KplerIndexItem, 0)
+
+	// 请求API获取数据
+	e := data.AddKplerIndex(params, productNamesStr, fromZoneNamesStr, toZoneNamesStr)
+	if e != nil {
+		br.Msg = "新增指标失败"
+		br.ErrMsg = fmt.Sprintf("新增指标失败, %v", e)
+		return
+	}
+	
+
+	br.Data = resp
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+}
+
+// KplerClassify
+// @Title Kpler数据分类
+// @Description Kpler数据分类接口
+// @Success 200 {object} data_manage.BaseFromKplerClassify
+// @router /kpler/classify [get]
+func (this *BaseFromKplerController) KplerClassify() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+    classifyId, _ := this.GetInt("ClassifyId")
+	if classifyId < 0 {
+		br.Msg = "请选择分类"
+		br.ErrMsg = "请选择分类"
+		return
+	}
+	list, e := data_manage.GetKplerClassifyAndIndex(classifyId)
+	if e != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取数据失败,Err:" + e.Error()
+		return
+	}
+
+	//组装二级分类
+	var ret data_manage.BaseFromKplerClassifyResp
+	ret.List = list
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = ret
+}
+
+// KplerClassifyTree
+// @Title Kpler数据分类树
+// @Description Kpler数据分类树接口
+// @Success 200 {object} data_manage.BaseFromKplerClassify
+// @router /kpler/classify/tree [get]
+func (this *BaseFromKplerController) KplerClassifyTree() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+    classifyAll := make([]*data_manage.BaseFromKplerClassifyItems, 0)
+	var err error
+	keyword := this.GetString("Keyword")
+	if keyword != "" {
+		keyList, er := data_manage.GetBaseFromKplerClassifyByKeyword(keyword)
+		if er != nil && !utils.IsErrNoRow(er) {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取数据失败,Err:" + er.Error()
+			return
+		}
+        classifyIds := make([]int, 0)
+		classifyMap := make(map[int]int)
+		for _, v := range keyList {
+			tmpIds := strings.Split(v.LevelPath, ",")
+			for _, id := range tmpIds {
+				tmpId, err := strconv.Atoi(id)
+				if err == nil {
+					if _, ok := classifyMap[tmpId]; !ok {
+						classifyIds = append(classifyIds, tmpId)
+						classifyMap[tmpId] = v.ClassifyId
+					}
+				}
+			}
+		}
+		classifyAll, err = data_manage.GetBaseFromKplerClassifyItemsByIds(classifyIds)
+		if err != nil && !utils.IsErrNoRow(err) {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取数据失败,Err:" + err.Error()
+			return
+		}
+	}
+	
+
+	list := data.GetKplerClassifyTreeRecursive(classifyAll, 0)
+
+	// 递归组装分类
+	var ret data_manage.BaseFromKplerClassifyResp
+	ret.List = list
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = ret
+}
+
+// 查询区域
+// @Title 查询区域
+// @Description 查询区域接口
+// @Success 200 {object} data_manage.BaseFromKplerZone
+// @router /kpler/zone [get]
+func (this *BaseFromKplerController) KplerZone() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	
+	keyword := this.GetString("Keyword")
+	var zoneList []*data_manage.BaseFromKplerZone
+	var err error
+	if keyword == "" {
+        br.Data = zoneList
+		br.Ret = 200
+		br.Success = true
+		br.Msg = "获取成功"
+		return
+	}
+	
+	// 使用带相似度排序的搜索函数
+	zoneList, err = data_manage.GetBaseFromKplerZoneByKeywordWithRelevance(keyword)
+	if err != nil && !utils.IsErrNoRow(err) {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+		return
+	}
+
+	br.Data = zoneList
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+}
+
+// KplerIndexData
+// @Title 获取Kpler数据
+// @Description 获取Kpler数据接口
+// @Param   PageSize   query   int  true       "每页数据条数"
+// @Param   CurrentIndex   query   int  true       "当前页页码,从1开始"
+// @Param   ClassifyId   query   string  true       "分类id"
+// @Success 200 {object} data_manage.LzFrequency
+// @router /kpler/index/data [get]
+func (this *BaseFromKplerController) KplerIndexData() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+
+	pageSize, _ := this.GetInt("PageSize")
+	currentIndex, _ := this.GetInt("CurrentIndex")
+	var startSize int
+
+	if pageSize <= 0 {
+		pageSize = utils.PageSize20
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	startSize = utils.StartIndex(currentIndex, pageSize)
+
+	classifyId, _ := this.GetInt("ClassifyId")
+	if classifyId < 0 {
+		br.Msg = "请选择分类"
+		br.ErrMsg = "请选择分类"
+		return
+	}
+	// 增加频度请求入参
+	frequency := this.GetString("Frequency")
+
+	//获取指标
+	var condition string
+	var pars []interface{}
+
+	if classifyId >= 0 {
+		classifyInfo, err := data_manage.GetBaseFromKplerClassifyById(classifyId)
+		if err != nil {
+			if utils.IsErrNoRow(err) {
+				br.Msg = "分类不存在"
+				return
+			}
+			br.Msg = "获取分类信息失败"
+			br.ErrMsg = "获取分类信息失败,Err:" + err.Error()
+			return
+		}
+		if classifyInfo.Level == 2 || classifyInfo.ParentId > 0 {
+			condition += ` AND classify_id=? `
+			pars = append(pars, classifyId)
+		} else if classifyInfo.Level == 1 {
+			childClassify, err := data_manage.GetBaseFromKplerClassifyByParentId(classifyId)
+			if err != nil {
+				br.Msg = "获取分类信息失败"
+				br.ErrMsg = "获取子分类信息失败,Err:" + err.Error()
+				return
+			}
+			var classifyList []int
+			for _, v := range childClassify {
+				classifyList = append(classifyList, v.ClassifyId)
+			}
+			condition += ` AND classify_id IN (` + utils.GetOrmInReplace(len(classifyList)) + `) `
+			pars = append(pars, classifyList)
+		}
+	}
+	if frequency != "" {
+		condition += ` AND frequency=? `
+		pars = append(pars, frequency)
+	}
+
+	KplerList, err := data_manage.GetKplerIndex(condition, pars)
+	if err != nil {
+		br.Msg = "获取数据失败"
+		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+		return
+	}
+
+	edbCodeList := make([]string, 0)
+	for _, v := range KplerList {
+		edbCodeList = append(edbCodeList, v.IndexCode)
+	}
+	edbInfoMap := make(map[string]*data_manage.EdbInfo)
+	dataMap := make(map[string][]*data_manage.BaseFromKplerData)
+	total := 0
+	if len(edbCodeList) > 0 {
+		edbInfoList, err := data_manage.GetEdbInfoByEdbCodeList(utils.DATA_SOURCE_KPLER, edbCodeList)
+		if err != nil {
+			br.Msg = "获取数据源失败"
+			br.ErrMsg = "获取指标数据失败,Err:" + err.Error()
+			return
+		}
+		for _, v := range edbInfoList {
+			edbInfoMap[v.EdbCode] = v
+		}
+		// 首先对分类下的指标按照日期进行分页,再针对日期,进行排序
+		dataTimes, err := data_manage.GetKplerIndexDataTimePageByCodes(edbCodeList, startSize, pageSize)
+		if err != nil {
+			br.Msg = "获取数据失败"
+			br.ErrMsg = "获取指标数据日期信息失败,Err:" + err.Error()
+			return
+		}
+		if len(dataTimes) > 0 {
+			startDate := dataTimes[len(dataTimes)-1]
+			endDate := dataTimes[0]
+			// 把截止日往后加1天
+			endDateT, _ := time.ParseInLocation(utils.FormatDate, endDate, time.Local)
+			endDate = endDateT.AddDate(0, 0, 1).Format(utils.FormatDate)
+			dataList, e := data_manage.GetKplerIndexDataByDataTime(edbCodeList, startDate, endDate)
+			if e != nil {
+				br.Msg = "获取数据失败"
+				br.ErrMsg = "获取指标数据失败,Err:" + e.Error()
+				return
+			}
+			//将数据按照指标进行分类
+			for _, v := range dataList {
+				dataMap[v.IndexCode] = append(dataMap[v.IndexCode], v)
+			}
+		}
+
+		total, err = data_manage.GetKplerIndexDataTimePageCount(edbCodeList)
+		if err != nil {
+			br.Msg = "获取数据失败"
+			br.ErrMsg = "获取指标数据失败,Err:" + err.Error()
+			return
+		}
+	}
+
+	page := paging.GetPaging(currentIndex, pageSize, total)
+
+	resultList := make([]*data_manage.BaseFromKplerIndexList, 0)
+
+	for _, v := range KplerList {
+		product := new(data_manage.BaseFromKplerIndexList)
+		product.BaseFromKplerIndexId = v.BaseFromKplerIndexId
+		product.Unit = v.Unit
+		product.IndexCode = v.IndexCode
+		product.IndexName = v.IndexName
+		product.Frequency = v.Frequency
+		product.ModifyTime = v.ModifyTime
+		if edb, ok := edbInfoMap[v.IndexCode]; ok {
+			product.EdbInfoId = edb.EdbInfoId
+			product.EdbExist = 1
+		}
+
+		dataListTmp, ok := dataMap[v.IndexCode]
+		if !ok {
+			dataListTmp = make([]*data_manage.BaseFromKplerData, 0)
+		}
+		product.DataList = dataListTmp
+		product.Paging = page
+		resultList = append(resultList, product)
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resultList
+}
+
+// KplerSearchList
+// @Title Kpler模糊搜索
+// @Description Kpler模糊搜索
+// @Param   Keyword   query   string  ture       "关键字搜索"
+// @Success 200 {object} models.BaseResponse
+// @router /kpler/search_list [get]
+func (this *BaseFromKplerController) KplerSearchList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请重新登录"
+		return
+	}
+
+	list := make([]*data_manage.BaseFromKplerIndexSearchItem, 0)
+	var err error
+	//关键字
+	keyword := this.GetString("Keyword")
+	if keyword != "" {
+		keyWordArr := strings.Split(keyword, " ")
+
+		if len(keyWordArr) > 0 {
+			condition := ""
+			for _, v := range keyWordArr {
+				condition += ` AND CONCAT(index_name,index_code) LIKE '%` + v + `%'`
+			}
+			list, err = data_manage.GetKplerItemList(condition)
+			if err != nil {
+				br.ErrMsg = "获取失败,Err:" + err.Error()
+				br.Msg = "获取失败"
+				return
+			}
+		}
+
+	} else {
+		// todo es 模糊搜索
+		list, err = data_manage.GetKplerItemList("")
+		if err != nil {
+			br.ErrMsg = "获取失败,Err:" + err.Error()
+			br.Msg = "获取失败"
+			return
+		}
+	}
+	classifyIds := make([]int, 0)
+	for _, v := range list {
+		classifyIds = append(classifyIds, v.ClassifyId)
+	}
+	classifyList, err := data_manage.GetBaseFromKplerClassifyByIds(classifyIds)
+	if err != nil {
+		br.Msg = "搜索失败"
+		br.ErrMsg = "获取分类信息失败,Err:" + err.Error()
+		return
+	}
+	classifyMap := make(map[int]int)
+	for _, v := range classifyList {
+		classifyMap[v.ClassifyId] = v.ParentId
+	}
+	for _, v := range list {
+		v.ParentClassifyId = classifyMap[v.ClassifyId]
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = list
+}
+
+// KplerSingleData
+// @Title 获取Kpler数据
+// @Description 获取Kpler单条数据接口
+// @Param   IndexCode   query   string  true       "指标唯一编码"
+// @Success 200 {object} models.BaseResponse
+// @router /kpler/single_data [get]
+func (this *BaseFromKplerController) KplerSingleData() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	indexCode := this.GetString("IndexCode")
+	indexInfo, err := data_manage.GetBaseFromKplerIndexByIndexCode(indexCode)
+	if err != nil {
+		br.Msg = "获取指标信息失败"
+		br.ErrMsg = "获取指标信息失败,Err:" + err.Error()
+		return
+	}
+	dataTmpList, err := data_manage.GetKplerIndexDataByCode(indexCode)
+	if err != nil {
+		br.Msg = "获取数据失败"
+		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+		return
+	}
+	edbInfo, err := data_manage.GetEdbInfoByEdbCode(utils.DATA_SOURCE_KPLER, indexCode)
+	if err != nil && !utils.IsErrNoRow(err) {
+		br.Msg = "获取数据源失败"
+		br.ErrMsg = "获取数据源失败,Err:" + err.Error()
+		return
+	}
+
+	var ret data_manage.KplerSingleDataResp
+	var dataList []*data_manage.KplerSingleData
+
+	if edbInfo != nil {
+		ret.EdbInfoId = edbInfo.EdbInfoId
+		ret.EdbExist = 1
+	}
+	ret.ClassifyId = indexInfo.ClassifyId
+	ret.BaseFromKplerIndexId = indexInfo.BaseFromKplerIndexId
+	ret.IndexCode = indexInfo.IndexCode
+	ret.IndexName = indexInfo.IndexName
+	ret.Frequency = indexInfo.Frequency
+	ret.CreateTime = indexInfo.CreateTime.Format(utils.FormatDateTime)
+	ret.ModifyTime = indexInfo.ModifyTime.Format(utils.FormatDateTime)
+	ret.Unit = indexInfo.Unit
+	for _, v := range dataTmpList {
+		tmp := &data_manage.KplerSingleData{
+			Value:    fmt.Sprintf("%v", v.Value),
+			DataTime: v.DataTime,
+		}
+		dataList = append(dataList, tmp)
+	}
+	ret.Data = dataList
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = ret
+}
+
+// KplerIndexList
+// @Title Kpler指标列表
+// @Description Kpler指标列表
+// @Param   ClassifyId   query   int  true       "分类id"
+// @Success 200 {object} data_manage.BaseFromKplerClassifyResp
+// @router /kpler/classify/index/list [get]
+func (this *BaseFromKplerController) KplerIndexList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	classifyId, _ := this.GetInt("ClassifyId", 0)
+	indexList, err := data_manage.GetKplerIndexByClassifyId(classifyId)
+	if err != nil && !utils.IsErrNoRow(err) {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取指标信息失败,Err:" + err.Error()
+		return
+	}
+
+	var ret data_manage.BaseFromKplerClassifyResp
+	list := make([]*data_manage.BaseFromKplerClassifyItems, 0)
+	for _, v := range indexList {
+		classify := new(data_manage.BaseFromKplerClassifyItems)
+		classify.ClassifyId = classifyId
+		classify.BaseFromKplerIndexId = v.BaseFromKplerIndexId
+		classify.IndexCode = v.IndexCode
+		classify.ClassifyName = v.IndexName
+		classify.UniqueCode = fmt.Sprintf("%d_%d", classifyId, v.BaseFromKplerIndexId)
+		list = append(list, classify)
+	}
+	ret.List = list
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = ret
+}
+
+// KplerBatchSearch
+// @Title Kpler指标查询
+// @Description Kpler指标查询
+// @Param   ClassifyIds   query   string  true       "分类id, 多个分类用英文"
+// @Param   Keyword   query   string  true       "关键词, 指标ID/指标名称"
+// @Success 200 {object} data_manage.LzFrequency
+// @router /kpler/batch_search [get]
+func (this *BaseFromKplerController) KplerBatchSearch() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	classifyIdStr := this.GetString("ClassifyIds")
+	pageSize, _ := this.GetInt("PageSize")
+	currentIndex, _ := this.GetInt("CurrentIndex")
+	var startSize int
+
+	if pageSize <= 0 {
+		pageSize = utils.PageSize20
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	startSize = utils.StartIndex(currentIndex, pageSize)
+	resp := data_manage.BaseFromKplerIndexSearchList{}
+	total := 0
+	page := paging.GetPaging(currentIndex, pageSize, total)
+	var list = make([]*data_manage.BaseFromKplerIndexList, 0)
+	var condition string
+	var pars []interface{}
+	classifyIds := strings.Split(classifyIdStr, ",")
+	if len(classifyIds) > 0 && classifyIds[0] != `` {
+		condition += " AND classify_id IN (" + utils.GetOrmInReplace(len(classifyIds)) + " ) "
+		pars = append(pars, classifyIds)
+	}
+	keyword := this.GetString("Keyword")
+	if keyword != `` {
+		condition += " AND (index_name like ? OR index_code like ?) "
+		pars = utils.GetLikeKeywordPars(pars, keyword, 2)
+	}
+	frequencies := this.GetString("Frequencies")
+	if frequencies != "" {
+		frequencyList := strings.Split(frequencies, ",")
+		condition += " AND frequency IN (" + utils.GetOrmInReplace(len(frequencyList)) + " ) "
+		pars = append(pars, frequencyList)
+	}
+	
+	condition += ` AND index_code not in (SELECT edb_code FROM edb_info WHERE source=?) `
+	pars = append(pars, "Kpler")
+
+	list, err := data_manage.GetKplerIndexPage(condition, pars, startSize, pageSize)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+	total, err = data_manage.GetKplerIndexPageCount(condition, pars)
+	if err != nil {
+		br.Msg = "获取数据失败"
+		br.ErrMsg = "获取指标数据失败,Err:" + err.Error()
+		return
+	}
+	page = paging.GetPaging(currentIndex, pageSize, total)
+	resp.Paging = page
+	resp.List = list
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+// KplerBatchAdd
+// @Title Kpler批量新增
+// @Description Kpler批量新增
+// @Param	request	body data_manage.AddEdbInfoReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /kpler/batch_add [post]
+func (this *BaseFromKplerController) KplerBatchAdd() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+
+	deleteCache := true
+	cacheKey := "CACHE_EDB_INFO_BATCH_ADD_Kpler_" + strconv.Itoa(sysUser.AdminId)
+	defer func() {
+		if deleteCache {
+			_ = utils.Rc.Delete(cacheKey)
+		}
+	}()
+	if !utils.Rc.SetNX(cacheKey, 1, 30*time.Second) {
+		deleteCache = false
+		br.Msg = "系统处理中,请稍后重试!"
+		br.ErrMsg = "系统处理中,请稍后重试!" + sysUser.RealName + ";data:" + string(this.Ctx.Input.RequestBody)
+		return
+	}
+	var req []*data_manage.AddEdbInfoReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + e.Error()
+		return
+	}
+	if len(req) == 0 {
+		br.Msg = "请选择指标"
+		return
+	}
+	if len(req) > 30 {
+		br.Msg = "批量添加指标数量不得超过30个"
+		return
+	}
+	for _, v := range req {
+		v.EdbCode = strings.TrimSpace(v.EdbCode)
+		if v.EdbCode == "" {
+			br.Msg = "指标ID不可为空"
+			return
+		}
+		v.EdbName = strings.TrimSpace(v.EdbName)
+		if v.EdbName == "" {
+			br.Msg = "请输入指标名称"
+			return
+		}
+		v.Frequency = strings.TrimSpace(v.Frequency)
+		if v.Frequency == "" {
+			br.Msg = "请选择频度"
+			return
+		}
+		v.Unit = strings.TrimSpace(v.Unit)
+		if v.Unit == "" {
+			br.Msg = "请输入单位"
+			return
+		}
+		if v.ClassifyId <= 0 {
+			br.Msg = "请选择分类"
+			return
+		}
+	}
+
+	// 限定同一时间最多批量新增30个指标
+	for _, v := range req {
+		var r data_manage.KplerIndexSource2EdbReq
+		r.EdbCode = v.EdbCode
+		r.EdbName = v.EdbName
+		r.Frequency = v.Frequency
+		r.Unit = v.Unit
+		r.ClassifyId = v.ClassifyId
+		r.AdminId = sysUser.AdminId
+		r.AdminRealName = sysUser.RealName
+
+		edbInfo, e, errMsg, skip := data.KplerIndexSource2Edb(r, this.Lang)
+		if e != nil {
+			br.Msg = "操作失败"
+			if errMsg != "" {
+				br.Msg = errMsg
+			}
+			br.ErrMsg = e.Error()
+			return
+		}
+		if skip {
+			continue
+		}
+
+		// 试用平台更新用户累计新增指标数
+		if utils.BusinessCode == utils.BusinessCodeSandbox {
+			go func() {
+				adminItem, e := system.GetSysAdminById(sysUser.AdminId)
+				if e != nil {
+					tips := fmt.Sprintf("试用平台更新用户累计新增指标数-获取用户失败, Err: " + e.Error())
+					utils.FileLog.Info(tips)
+					return
+				}
+				if adminItem.DepartmentName != "ETA试用客户" {
+					return
+				}
+				var ur etaTrialService.EtaTrialUserReq
+				ur.Mobile = adminItem.Mobile
+				_, _ = etaTrialService.UpdateUserIndexNum(ur)
+			}()
+		}
+
+		// 新增操作日志
+		{
+			edbLog := new(data_manage.EdbInfoLog)
+			edbLog.EdbInfoId = edbInfo.EdbInfoId
+			edbLog.SourceName = edbInfo.SourceName
+			edbLog.Source = edbInfo.Source
+			edbLog.EdbCode = edbInfo.EdbCode
+			edbLog.EdbName = edbInfo.EdbName
+			edbLog.ClassifyId = edbInfo.ClassifyId
+			edbLog.SysUserId = sysUser.AdminId
+			edbLog.SysUserRealName = sysUser.RealName
+			edbLog.CreateTime = time.Now()
+			edbLog.Content = string(this.Ctx.Input.RequestBody)
+			edbLog.Status = "新增指标"
+			edbLog.Method = this.Ctx.Input.URI()
+			go data_manage.AddEdbInfoLog(edbLog)
+		}
+	}
+
+	br.Msg = "操作成功"
+	br.Ret = 200
+	br.Success = true
+	br.IsAddLog = true
+}
+
+// KplerNameCheck
+// @Title 加入指标库的重名检测
+// @Description 加入指标库的重名检测
+// @Param   ClassifyIds   query   string  true       "分类id, 多个分类用英文"
+// @Param   Keyword   query   string  true       "关键词, 指标ID/指标名称"
+// @Success 200 {object} NameCheckResult
+// @router /kpler/edb_info/name_check [post]
+func (this *BaseFromKplerController) KplerNameCheck() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	var req []*data_manage.NameCheckEdbInfoReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + e.Error()
+		return
+	}
+	if len(req) == 0 {
+		br.Msg = "请选择指标"
+		return
+	}
+	codeMaxT := 30
+	codeLen := len(req)
+	if codeLen > codeMaxT {
+		br.Msg = "批量添加指标数量不得超过30个"
+		return
+	}
+
+	indexNames := make([]string, 0)
+	resp := make([]*data_manage.EdbNameCheckResult, 0)
+	for _, v := range req {
+		v.EdbCode = strings.TrimSpace(v.EdbCode)
+		if v.EdbCode == "" {
+			br.Msg = "指标ID不可为空"
+			return
+		}
+		v.EdbName = strings.TrimSpace(v.EdbName)
+		if v.EdbName == "" {
+			br.Msg = "请输入指标名称"
+			return
+		}
+		indexNames = append(indexNames, v.EdbName)
+		resp = append(resp, &data_manage.EdbNameCheckResult{
+			EdbCode: v.EdbCode,
+			EdbName: v.EdbName,
+		})
+		dataItems, err := data_manage.GetEdbDataAllByEdbCode(v.EdbCode, utils.DATA_SOURCE_KPLER, 0, utils.EDB_DATA_LIMIT)
+		if err != nil && !utils.IsErrNoRow(err) {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取钢联已存在信息失败,Err:" + err.Error()
+			return
+		}
+		if len(dataItems) <= 0 {
+			respItem, err := data.AddEdbData(utils.DATA_SOURCE_KPLER, v.EdbCode, v.Frequency)
+			if err != nil {
+				br.Msg = "获取失败"
+				br.ErrMsg = "获取失败,Err:" + err.Error()
+				return
+			}
+			if respItem.Ret != 200 {
+				br.Msg = "未搜索到该指标"
+				br.ErrMsg = respItem.ErrMsg + ";EdbCode:" + v.EdbCode
+				return
+			}
+		}
+	}
+
+	// 重名校验
+	edbList, e := data_manage.GetEdbInfoByNameArr(indexNames, utils.EDB_INFO_TYPE)
+	if e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "获取重名指标失败, Err: " + e.Error()
+		return
+	}
+	nameExists := make(map[string]bool)
+	for _, v := range edbList {
+		nameExists[v.EdbName] = true
+	}
+	if len(nameExists) > 0 {
+		for _, v := range resp {
+			v.Exist = nameExists[v.EdbName]
+		}
+	}
+
+	br.Data = resp
+	br.Msg = "校验成功"
+	br.Ret = 200
+	br.Success = true
+}
+
+// KplerAddCheck
+// @Title 加入指标库指标Id检测
+// @Description 加入指标库指标Id检测
+// @Param	request	body request.BatchAddCheckReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /kpler/edb_info/add_check [post]
+func (c *BaseFromKplerController) KplerAddCheck() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	sysUser := c.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	var req data_manage.BatchAddCheckReq
+	if e := json.Unmarshal(c.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + e.Error()
+		return
+	}
+	codeMaxT := 30
+	codeLen := len(req.IndexCodes)
+
+	// 获取指标库已有指标
+	existsEdb, e := data_manage.GetEdbCodesBySource(utils.DATA_SOURCE_KPLER)
+	if e != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取自有数据已添加的指标失败, Err: " + e.Error()
+		return
+	}
+	existMap := make(map[string]*data_manage.EdbInfo)
+	for _, v := range existsEdb {
+		existMap[v.EdbCode] = v
+	}
+
+	if codeLen == 0 {
+		br.Msg = "请选择指标"
+		return
+	}
+	if codeLen > codeMaxT {
+		br.Msg = fmt.Sprintf("最多只能选择%d个指标", codeMaxT)
+		return
+	}
+
+	// 查询选中的指标
+	cond := fmt.Sprintf(` AND index_code IN (%s)`, utils.GetOrmInReplace(codeLen))
+	pars := make([]interface{}, 0)
+	pars = append(pars, req.IndexCodes)
+	list, err := data_manage.GetKplerIndex(cond, pars)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取钢联已存在信息失败,Err:" + err.Error()
+		return
+	}
+
+	if len(list) > codeMaxT {
+		br.Msg = fmt.Sprintf("最多只能选择%d个指标", codeMaxT)
+		return
+	}
+
+	resp := make([]*data_manage.BaseFromKplerIndexList, 0)
+	for _, v := range list {
+		if edb, ok := existMap[v.IndexCode]; ok {
+			v.EdbInfoId = edb.EdbInfoId
+			v.EdbClassifyId = edb.ClassifyId
+			v.EdbUniqueCode = edb.UniqueCode
+			v.EdbExist = 1
+		}
+		resp = append(resp, v)
+	}
+
+	br.Data = resp
+	br.Msg = "校验成功"
+	br.Ret = 200
+	br.Success = true
+}
+
+// ExportKplerList
+// @Title 导出Kpler数据
+// @Description 导出Kpler数据
+// @Param   ClassifyId   query   int  true       "关键字搜索"
+// @Param   IndexCode   query   string  true       "指标编码"
+// @Success 200  导出成功
+// @router /kpler/export [get]
+func (this *BaseFromKplerController) ExportKplerList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请重新登录"
+		return
+	}
+
+	classifyId, _ := this.GetInt("ClassifyId")
+	indexCode := this.GetString("IndexCode")
+
+	if classifyId <= 0 && indexCode == "" {
+		br.Msg = "请选择分类或者指标"
+		return
+	}
+	dir, _ := os.Executable()
+	exPath := filepath.Dir(dir)
+	downLoadnFilePath := exPath + "/" + time.Now().Format(utils.FormatDateTimeUnSpace) + ".xlsx"
+	xlsxFile := xlsx.NewFile()
+
+	var condition string
+	var pars []interface{}
+	var classifyName string
+	if classifyId > 0 {
+		classifyInfo, err := data_manage.GetBaseFromKplerClassifyById(classifyId)
+		if err != nil {
+			if utils.IsErrNoRow(err) {
+				br.Msg = "分类不存在"
+				return
+			}
+			br.Msg = "下载失败"
+			br.ErrMsg = "获取分类失败,Err:" + err.Error()
+			return
+		}
+		classifyName = classifyInfo.ClassifyName
+		childClassify, err := data_manage.GetBaseFromKplerClassifyByParentId(classifyId)
+		if err != nil {
+			br.Msg = "下载失败"
+			br.ErrMsg = "获取分类失败,Err:" + err.Error()
+			return
+		}
+
+		if len(childClassify) > 0 {
+			condition += `AND classify_id IN (` + utils.GetOrmInReplace(len(childClassify)) + `)`
+			for _, child := range childClassify {
+				pars = append(pars, child.ClassifyId)
+			}
+		} else {
+			condition += ` AND classify_id=?`
+			pars = append(pars, classifyId)
+		}
+	}
+	if indexCode != "" {
+		condition += ` AND index_code=? `
+		pars = append(pars, indexCode)
+	}
+
+	indexList, err := data_manage.GetKplerIndex(condition, pars)
+	if err != nil {
+		br.Msg = "下载失败"
+		br.ErrMsg = "获取指标失败,Err:" + err.Error()
+		fmt.Println("获取数据失败,Err:" + err.Error())
+		return
+	}
+	if len(indexList) <= 0 {
+		fmt.Println("indexList 为空")
+		br.Ret = 200
+		br.Success = true
+		br.Msg = "success"
+		return
+	}
+
+	codeList := make([]string, 0)
+	frequenciesMap := make(map[string][]*data_manage.BaseFromKplerIndexList)
+	for _, v := range indexList {
+		codeList = append(codeList, v.IndexCode)
+		frequenciesMap[v.Frequency] = append(frequenciesMap[v.Frequency], v)
+	}
+	dataListMap := make(map[string][]*data_manage.BaseFromKplerData)
+	if len(indexList) > 0 {
+		allDataList, e := data_manage.GetKplerIndexDataByCodes(codeList)
+		if e != nil {
+			br.Msg = "获取数据失败"
+			br.ErrMsg = "获取数据失败,Err:" + e.Error()
+			return
+		}
+		for _, v := range allDataList {
+			dataListMap[v.IndexCode] = append(dataListMap[v.IndexCode], v)
+		}
+	}
+	// 按照频率分组排序
+	frequencies := []string{
+		"日度", "周度", "旬度", "月度", "季度", "半年度", "年度",
+	}
+	for _, frequency := range frequencies {
+		//获取指标
+		indexCodeList, ok := frequenciesMap[frequency]
+		if !ok {
+			continue
+		}
+		if len(indexCodeList) <= 0 {
+			fmt.Printf("sheet:%s, 不存在指标", frequency)
+			return
+		}
+		var sheetName string
+		switch frequency {
+		case "日度":
+			sheetName = "日度(Daily)"
+		case "周度":
+			sheetName = "周度(Weekly)"
+		case "旬度":
+			sheetName = "旬度(ten-day)"
+		case "月度":
+			sheetName = "月度(Monthly)"
+		case "季度":
+			sheetName = "季度(Quarterly)"
+		case "半年度":
+			sheetName = "半年度(Semi-annual)"
+		case "年度":
+			sheetName = "年度(Annual)"
+		default:
+			sheetName = "其他数据"
+		}
+		sheetNew, err := xlsxFile.AddSheet(sheetName)
+		if err != nil {
+			fmt.Println("新增Sheet失败", err.Error())
+			return
+		}
+		secNameRow := sheetNew.AddRow()
+		frequencyRow := sheetNew.AddRow()
+		unitRow := sheetNew.AddRow()
+		lastModifyDateRow := sheetNew.AddRow()
+
+		var indexIdList []int
+		for _, idx := range frequenciesMap[frequency] {
+			indexIdList = append(indexIdList, idx.BaseFromKplerIndexId)
+		}
+		dataTimeList, err := data_manage.GetKplerDataDataTimeByIndexId(indexIdList)
+		if err != nil {
+			br.Msg = "下载失败"
+			br.ErrMsg = "获取数据时间失败,Err:" + err.Error()
+			fmt.Println("获取数据时间失败", err.Error())
+			return
+		}
+
+		// 添加excel左侧指标日期
+		setRowIndex := 4
+		for rk, dv := range dataTimeList {
+			rowIndex := setRowIndex + rk
+			row := sheetNew.Row(rowIndex)
+			displayDate, _ := time.Parse(utils.FormatDate, dv)
+			displayDateCell := row.AddCell()
+			style := new(xlsx.Style)
+			style.ApplyAlignment = true
+			style.Alignment.WrapText = true
+			displayDateCell.SetStyle(style)
+			displayDateCell.SetDate(displayDate)
+
+		}
+		for k, icl := range indexCodeList {
+			// 获取数据
+			dataList, ok := dataListMap[icl.IndexCode]
+			if !ok {
+				continue
+			}
+			if k == 0 {
+				secNameRow.AddCell().SetValue("指标名称/Metric Name")
+				frequencyRow.AddCell().SetValue("频度/Frequency")
+				unitRow.AddCell().SetValue("单位/Unit")
+				lastModifyDateRow.AddCell().SetValue("更新时间/Update Time")
+				min := k * 3
+				sheetNew.SetColWidth(min, min, 15)
+			}
+			if len(dataList) == 0 {
+				continue
+			}
+			secNameRow.AddCell().SetValue(icl.IndexName)
+			frequencyRow.AddCell().SetValue(icl.Frequency)
+			unitRow.AddCell().SetValue(icl.Unit)
+
+			timeDate, err := time.Parse(utils.FormatDateTime, dataList[0].ModifyTime)
+			if err != nil {
+				continue
+			}
+			lastModifyDateRow.AddCell().SetValue(timeDate.Format(utils.FormatDate))
+			dataInfoMap := make(map[string]*data_manage.BaseFromKplerData)
+			for _, v := range dataList {
+				dataInfoMap[v.DataTime] = v
+			}
+
+			for rk, dtv := range dataTimeList {
+				rowIndex := setRowIndex + rk
+				row := sheetNew.Row(rowIndex)
+				displayDateCell := row.AddCell()
+				tmpData, ok := dataInfoMap[dtv]
+				if ok {
+					displayDateCell.SetValue(tmpData.Value)
+				}
+			}
+		}
+	}
+
+	err = xlsxFile.Save(downLoadnFilePath)
+	if err != nil {
+		//有指标无数据时先导出一遍空表
+		sheet, err := xlsxFile.AddSheet("无数据")
+		if err != nil {
+			br.Msg = "新增Sheet失败"
+			br.ErrMsg = "新增Sheet失败,Err:" + err.Error()
+			return
+		}
+		rowSecName := sheet.AddRow()
+		celSecName := rowSecName.AddCell()
+		celSecName.SetValue("")
+		e := xlsxFile.Save(downLoadnFilePath)
+		if e != nil {
+			br.Msg = "保存文件失败"
+			br.ErrMsg = "保存文件失败"
+			return
+		}
+	}
+
+	fileName := classifyName
+	if indexCode != "" && len(indexList) == 1 {
+		fileName = indexList[0].IndexName
+	}
+	fileName = strings.Replace(fileName, ": ", "_", -1)
+	fileName = strings.Replace(fileName, ", ", "_", -1)
+	fileName = strings.Replace(fileName, " ", "_", -1)
+	fileName += time.Now().Format("06.01.02") + `.xlsx` //文件名称
+	fmt.Println(fileName)
+	this.Ctx.Output.Download(downLoadnFilePath, fileName)
+	defer func() {
+		os.Remove(downLoadnFilePath)
+	}()
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "success"
+} 

+ 241 - 0
models/data_manage/base_from_kpler_classify.go

@@ -0,0 +1,241 @@
+package data_manage
+
+import (
+	"eta/eta_api/global"
+	"eta/eta_api/utils"
+	"time"
+)
+
+// 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:"产品名称"`
+	LevelPath       string    `description:"层级路径"`
+}
+
+// AddBaseFromKplerClassify 添加Kpler原始数据分类
+func AddBaseFromKplerClassify(item *BaseFromKplerClassify) (lastId int64, err error) {
+	o := global.DbMap[utils.DbNameIndex]
+	err = o.Create(item).Error
+	return
+}
+
+// GetBaseFromKplerClassifyCount 获取分类名称的个数
+func GetBaseFromKplerClassifyCount(classifyName string, parentId int) (count int, err error) {
+	o := global.DbMap[utils.DbNameIndex]
+	sql := `SELECT COUNT(1) AS count FROM base_from_kpler_classify WHERE classify_name=? AND parent_id=? `
+	err = o.Raw(sql, classifyName, parentId).Scan(&count).Error
+	return
+}
+
+// GetBaseFromKplerClassifyById 通过分类id的获取分类信息
+func GetBaseFromKplerClassifyById(classifyId int) (item *BaseFromKplerClassify, err error) {
+	o := global.DbMap[utils.DbNameIndex]
+	sql := `SELECT * FROM base_from_kpler_classify WHERE classify_id=? `
+	err = o.Raw(sql, classifyId).First(&item).Error
+	return
+}
+
+// GetBaseFromKplerClassifyByIds 通过分类id的获取分类信息
+func GetBaseFromKplerClassifyByIds(classifyIds []int) (items []*BaseFromKplerClassify, err error) {
+	if len(classifyIds) == 0 {
+		return
+	}
+	o := global.DbMap[utils.DbNameIndex]
+	sql := `SELECT * FROM base_from_kpler_classify WHERE classify_id IN (` + utils.GetOrmInReplace(len(classifyIds)) + `) `
+	err = o.Raw(sql, classifyIds).Find(&items).Error
+	return
+}
+
+// GetBaseFromKplerClassifyItemsByIds 通过分类id的获取分类信息
+func GetBaseFromKplerClassifyItemsByIds(classifyIds []int) (items []*BaseFromKplerClassifyItems, err error) {
+	if len(classifyIds) == 0 {
+		return
+	}
+	o := global.DbMap[utils.DbNameIndex]
+	sql := `SELECT * FROM base_from_kpler_classify WHERE classify_id IN (` + utils.GetOrmInReplace(len(classifyIds)) + `) `
+	err = o.Raw(sql, classifyIds).Find(&items).Error
+	return
+}
+
+// EditBaseFromKplerClassify 修改Kpler原始数据分类
+func EditBaseFromKplerClassify(classifyId int, classifyName string) (err error) {
+	o := global.DbMap[utils.DbNameIndex]
+	sql := `UPDATE base_from_kpler_classify SET classify_name=?,modify_time=NOW() WHERE classify_id=? `
+	err = o.Exec(sql, classifyName, classifyId).Error
+	return
+}
+
+// UpdateBaseFromKplerClassifySort 修改Kpler原始数据分类的排序
+func UpdateBaseFromKplerClassifySort(classifyId int) (err error) {
+	o := global.DbMap[utils.DbNameIndex]
+	sql := `UPDATE base_from_kpler_classify SET sort=classify_id, modify_time=NOW() WHERE classify_id=? `
+	err = o.Exec(sql, classifyId).Error
+	return
+}
+
+type BaseFromKplerClassifyItems struct {
+	ClassifyId            int                          `description:"分类ID"`
+	BaseFromKplerIndexId  int                          `description:"指标类型ID"`
+	IndexCode             string                       `description:"指标唯一编码"`
+	ClassifyName          string                       `description:"分类名称"`
+	ClassifyNameEn        string                       `description:"英文分类名称"`
+	UniqueCode            string                       `description:"分类唯一编码"`
+	ParentId              int                          `description:"父级id"`
+	Level                 int                          `description:"层级"`
+	Sort                  int                          `description:"排序字段,越小越靠前,默认值:10"`
+	ProductId             int                          `description:"产品ID"`
+	ProductName           string                       `description:"产品名称"`
+	Children              []*BaseFromKplerClassifyItems `description:"子级" gorm:"-"`
+	LevelPath             string                       `description:"层级路径"`
+}
+
+type BaseFromKplerClassifyNameItems struct {
+	ClassifyId   int    `description:"分类ID"`
+	ClassifyName string `description:"分类名称"`
+	ParentId     int    `description:"父级id"`
+}
+
+type BaseFromKplerClassifyResp struct {
+	List []*BaseFromKplerClassifyItems
+}
+
+type BaseFromKplerClassifyNameResp struct {
+	List []*BaseFromKplerClassifyNameItems
+}
+
+type BaseFromKplerClassifyItemsButton struct {
+	AddButton    bool `description:"是否可添加"`
+	OpButton     bool `description:"是否可编辑"`
+	DeleteButton bool `description:"是否可删除"`
+	MoveButton   bool `description:"是否可移动"`
+}
+
+// GetBaseFromKplerClassifyByParentId 根据上级id获取当下的分类列表数据
+func GetBaseFromKplerClassifyByParentId(parentId int) (items []*BaseFromKplerClassifyItems, err error) {
+	o := global.DbMap[utils.DbNameIndex]
+	sql := ` SELECT * FROM base_from_kpler_classify WHERE parent_id=? order by sort asc,classify_id asc`
+	err = o.Raw(sql, parentId).Find(&items).Error
+	return
+}
+
+// GetAllBaseFromKplerClassify 获取所有的分类列表数据
+func GetAllBaseFromKplerClassify() (items []*BaseFromKplerClassifyItems, err error) {
+	o := global.DbMap[utils.DbNameIndex]
+	sql := ` SELECT * FROM base_from_kpler_classify order by parent_id asc, sort asc, classify_id asc`
+	err = o.Raw(sql).Find(&items).Error
+	return
+}
+
+// GetBaseFromKplerClassifyByKeyword 根据关键词获取分类列表数据
+func GetBaseFromKplerClassifyByKeyword(keyword string) (items []*BaseFromKplerClassifyItems, err error) {
+	o := global.DbMap[utils.DbNameIndex]
+	sql := ` SELECT * FROM base_from_kpler_classify WHERE classify_name LIKE ? order by parent_id asc, sort asc, classify_id asc`
+	err = o.Raw(sql, "%"+keyword+"%").Find(&items).Error
+	return
+}
+
+type BaseFromKplerClassifyListResp struct {
+	AllNodes      []*BaseFromKplerClassifyItems
+	CanOpClassify bool `description:"是否允许操作分类"`
+}
+
+type BaseFromKplerClassifySimplify struct {
+	ClassifyId   int    `description:"分类id"`
+	ClassifyName string `description:"分类名称"`
+	ParentId     int
+}
+
+// GetFirstBaseFromKplerClassify 获取当前分类下,且排序数相同 的排序第一条的数据
+func GetFirstBaseFromKplerClassify() (item *BaseFromKplerClassify, err error) {
+	o := global.DbMap[utils.DbNameIndex]
+	sql := ` SELECT * FROM base_from_kpler_classify order by sort asc,classify_id asc limit 1`
+	err = o.Raw(sql).First(&item).Error
+	return
+}
+
+
+
+// GetKplerIndexClassifyMinSort 获取最小不等于0的排序
+func GetKplerIndexClassifyMinSort(parentId int) (sort int, err error) {
+	o := global.DbMap[utils.DbNameIndex]
+	sql := `select min(sort) from base_from_kpler_classify where parent_id=? and sort <> 0 `
+	err = o.Raw(sql, parentId).Scan(&sort).Error
+	return
+}
+
+// Update 更新分类基础信息
+func (BaseFromKplerClassify *BaseFromKplerClassify) Update(cols []string) (err error) {
+	o := global.DbMap[utils.DbNameIndex]
+	err = o.Model(BaseFromKplerClassify).Select(cols).Updates(BaseFromKplerClassify).Error
+	return
+}
+
+type AddKplerClassifyResp struct {
+	ClassifyId int
+}
+
+// AddKplerClassifyMulti 批量新增Kpler类别
+func AddKplerClassifyMulti(list []*BaseFromKplerClassify) (err error) {
+	o := global.DbMap[utils.DbNameIndex]
+	err = o.CreateInBatches(list, utils.MultiAddNum).Error
+	return
+}
+
+func GetBaseFromKplerClassifyByLevelPath(levelPath string) (items []*BaseFromKplerClassify, err error) {
+	sql := `SELECT * FROM base_from_kpler_classify where level_path like '` + levelPath + `%'`
+	err = global.DbMap[utils.DbNameIndex].Raw(sql).Find(&items).Error
+	return
+}
+
+func GetKplerClassifyAndIndex(parentId int) (items []*BaseFromKplerClassifyItems, err error) {
+	o := global.DbMap[utils.DbNameIndex]
+	sql := `SELECT
+			0 AS base_from_kpler_index_id,
+			c.classify_id,
+			c.classify_name,
+			c.parent_id,
+			c.sort,
+			"" AS index_code
+		FROM
+			base_from_kpler_classify c
+		WHERE
+			c.parent_id = ?
+		
+		UNION ALL
+		
+		SELECT
+			i.base_from_kpler_index_id,
+			i.classify_id,
+			i.index_name AS classify_name,
+			0 AS parent_id,
+			i.sort,
+			i.index_code
+		FROM
+			base_from_kpler_index i
+		WHERE
+			i.classify_id = ?
+		
+		ORDER BY
+			sort ASC
+		`
+	err = o.Raw(sql, parentId, parentId).Find(&items).Error
+	return
+}
+
+func GetKplerClassifyByProductId(productIds []int) (items []*BaseFromKplerClassifyItems, err error) {
+	o := global.DbMap[utils.DbNameIndex]
+	sql := `SELECT * FROM base_from_kpler_classify WHERE product_id IN (?)`
+	err = o.Raw(sql, productIds).Find(&items).Error
+	return
+}

+ 430 - 0
models/data_manage/base_from_kpler_index.go

@@ -0,0 +1,430 @@
+package data_manage
+
+import (
+	"eta/eta_api/global"
+	"eta/eta_api/utils"
+	"time"
+
+	"gorm.io/gorm"
+
+	"github.com/rdlucklib/rdluck_tools/paging"
+)
+
+type BaseFromKplerIndex struct {
+	BaseFromKplerIndexId int `orm:"column(base_from_kpler_index_id);pk" gorm:"primaryKey"`
+	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:"拆分类型"`
+}
+
+type BaseFromKplerIndexList struct {
+	BaseFromKplerIndexId int `orm:"column(base_from_kpler_index_id);pk" gorm:"primaryKey"`
+	ClassifyId           int
+	Interface            string
+	EdbInfoId            int
+	EdbUniqueCode        string `description:"指标库唯一编码"`
+	EdbClassifyId        int    `description:"指标库分类ID"`
+	StartDate            string
+	EndDate              string
+	EndValue             float64
+	IndexCode            string
+	IndexName            string
+	Frequency            string
+	Unit                 string
+	Sort                 int
+	CreateTime           string
+	ModifyTime           string
+	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:"拆分类型"`
+	EdbExist             int                  `description:"指标库是否已添加:0-否;1-是"`
+	DataList             []*BaseFromKplerData `gorm:"-"`
+	Paging               *paging.PagingItem   `description:"分页数据" gorm:"-"`
+}
+
+func (obj *BaseFromKplerIndexList) AfterFind(db *gorm.DB) (err error) {
+	obj.CreateTime = utils.GormDateStrToDateTimeStr(obj.CreateTime)
+	obj.ModifyTime = utils.GormDateStrToDateTimeStr(obj.ModifyTime)
+	obj.StartDate = utils.GormDateStrToDateStr(obj.StartDate)
+	obj.EndDate = utils.GormDateStrToDateStr(obj.EndDate)
+	return
+}
+
+type BaseFromKplerIndexSearchList struct {
+	List   []*BaseFromKplerIndexList
+	Paging *paging.PagingItem `description:"分页数据"`
+}
+
+type KplerSingleDataResp struct {
+	BaseFromKplerIndexId int
+	ClassifyId           int
+	EdbInfoId            int
+	IndexCode            string
+	IndexName            string
+	Frequency            string
+	Unit                 string
+	StartTime            string
+	CreateTime           string
+	ModifyTime           string
+	EdbExist             int `description:"指标库是否已添加:0-否;1-是"`
+	Data                 []*KplerSingleData
+}
+
+type KplerSingleData struct {
+	Value    string `orm:"column(value)" description:"日期"`
+	DataTime string `orm:"column(data_time)" description:"值"`
+}
+
+func GetKplerIndexByClassifyId(classifyId int) (items []*BaseFromKplerIndex, err error) {
+	o := global.DbMap[utils.DbNameIndex]
+	sql := ` SELECT base_from_kpler_index_id, classify_id, index_code, index_name FROM base_from_kpler_index WHERE classify_id=? ORDER BY sort ASC, base_from_kpler_index_id ASC `
+	err = o.Raw(sql, classifyId).Find(&items).Error
+	return
+}
+
+func GetKplerIndex(condition string, pars []interface{}) (items []*BaseFromKplerIndexList, err error) {
+	o := global.DbMap[utils.DbNameIndex]
+	sql := ` SELECT * FROM base_from_kpler_index WHERE 1=1  `
+	if condition != "" {
+		sql += condition
+	}
+	sql += ` ORDER BY sort ASC, base_from_kpler_index_id asc`
+	err = o.Raw(sql, pars...).Find(&items).Error
+	return
+}
+
+func GetKplerIndexPage(condition string, pars []interface{}, startSize, pageSize int) (items []*BaseFromKplerIndexList, err error) {
+	o := global.DbMap[utils.DbNameIndex]
+	sql := ` SELECT * FROM base_from_kpler_index WHERE 1=1  `
+	if condition != "" {
+		sql += condition
+	}
+	sql += ` ORDER BY sort ASC, base_from_kpler_index_id asc LIMIT ?,?`
+	pars = append(pars, startSize, pageSize)
+	err = o.Raw(sql, pars...).Find(&items).Error
+	return
+}
+
+func GetKplerIndexPageCount(condition string, pars []interface{}) (count int, err error) {
+	o := global.DbMap[utils.DbNameIndex]
+	sql := ` SELECT COUNT(1) AS count  FROM base_from_kpler_index WHERE 1=1  `
+	if condition != "" {
+		sql += condition
+	}
+	err = o.Raw(sql, pars...).Scan(&count).Error
+	return
+}
+
+func GetKplerIndexDataCount(indexCode string) (count int, err error) {
+	o := global.DbMap[utils.DbNameIndex]
+	sql := ` SELECT COUNT(1) AS count  FROM base_from_kpler_data WHERE index_code=? `
+	err = o.Raw(sql, indexCode).Scan(&count).Error
+	return
+}
+
+func GetKplerIndexDataByDataTime(indexCodes []string, startDate, endDate string) (items []*BaseFromKplerData, err error) {
+	o := global.DbMap[utils.DbNameIndex]
+	sql := ` SELECT *  FROM base_from_kpler_data WHERE  index_code in (` + utils.GetOrmInReplace(len(indexCodes)) + `) and data_time >=? and data_time <? ORDER BY data_time DESC `
+	err = o.Raw(sql, indexCodes, startDate, endDate).Find(&items).Error
+	return
+}
+
+func GetKplerIndexDataTimePageByCodes(indexCodes []string, startSize, pageSize int) (dataTimes []string, err error) {
+	o := global.DbMap[utils.DbNameIndex]
+	sql := ` SELECT data_time FROM base_from_kpler_data WHERE index_code in (` + utils.GetOrmInReplace(len(indexCodes)) + `) GROUP BY data_time ORDER BY data_time DESC LIMIT ?,? `
+	err = o.Raw(sql, indexCodes, startSize, pageSize).Scan(&dataTimes).Error
+	for i := range dataTimes {
+		dataTimes[i] = utils.GormDateStrToDateStr(dataTimes[i])
+	}
+	return
+}
+
+func GetKplerIndexDataTimePageCount(indexCodes []string) (count int, err error) {
+	o := global.DbMap[utils.DbNameIndex]
+	sql := ` SELECT COUNT(DISTINCT data_time) AS count  FROM base_from_kpler_data WHERE index_code in (` + utils.GetOrmInReplace(len(indexCodes)) + `) `
+	err = o.Raw(sql, indexCodes).Scan(&count).Error
+	return
+}
+
+func GetKplerIndexDataByCodes(indexCode []string) (items []*BaseFromKplerData, err error) {
+	if len(indexCode) == 0 {
+		return
+	}
+	o := global.DbMap[utils.DbNameIndex]
+	sql := ` SELECT *  FROM base_from_kpler_data WHERE index_code in (` + utils.GetOrmInReplace(len(indexCode)) + `) ORDER BY data_time DESC  `
+	err = o.Raw(sql, indexCode).Find(&items).Error
+	return
+}
+
+// GetKplerByConditionAndFrequency 根据条件获取Kpler指标列表
+func GetKplerByConditionAndFrequency(condition, frequency string, pars []interface{}) (items []*BaseFromKplerIndex, err error) {
+	o := global.DbMap[utils.DbNameIndex]
+	sql := ` SELECT * FROM base_from_kpler_index WHERE 1=1 `
+
+	if condition != "" {
+		sql += condition
+	}
+	sql += ` AND frequency=?`
+	sql += ` ORDER BY sort ASC, base_from_kpler_index_id ASC`
+	err = o.Raw(sql, pars, frequency).Find(&items).Error
+	return
+}
+
+func GetKplerFrequencyByCondition(condition string, pars []interface{}) (items []string, err error) {
+	sql := `SELECT DISTINCT frequency FROM base_from_kpler_index WHERE 1=1 `
+	if condition != "" {
+		sql += condition
+	}
+	sql += ` ORDER BY FIELD(frequency,'日度','周度','旬度','月度','季度','半年度','年度') `
+	o := global.DbMap[utils.DbNameIndex]
+	err = o.Raw(sql, pars...).Find(&items).Error
+	return
+}
+
+// GetKplerDataDataTimeByIndexId 根据指标id获取指标数据的日期列表
+func GetKplerDataDataTimeByIndexId(indexIdList []int) (items []string, err error) {
+	if len(indexIdList) == 0 {
+		return
+	}
+	o := global.DbMap[utils.DbNameIndex]
+	sql := ` SELECT DISTINCT data_time FROM base_from_kpler_data WHERE base_from_kpler_index_id IN (` + utils.GetOrmInReplace(len(indexIdList)) + `) ORDER BY data_time DESC`
+	err = o.Raw(sql, indexIdList).Find(&items).Error
+	if err != nil {
+		return
+	}
+	for i := range items {
+		items[i] = utils.GormDateStrToDateStr(items[i])
+	}
+	return
+}
+
+type BaseFromKplerData struct {
+	BaseFromKplerDataId  int `orm:"column(base_from_kpler_data_id);pk" gorm:"primaryKey"`
+	BaseFromKplerIndexId int
+	IndexCode            string
+	DataTime             string
+	Value                float64
+	CreateTime           string
+	ModifyTime           string
+	DataTimestamp        int64
+}
+
+func (obj *BaseFromKplerData) AfterFind(tx *gorm.DB) (err error) {
+	obj.CreateTime = utils.GormDateStrToDateTimeStr(obj.CreateTime)
+	obj.ModifyTime = utils.GormDateStrToDateTimeStr(obj.ModifyTime)
+	obj.DataTime = utils.GormDateStrToDateStr(obj.DataTime)
+	return
+}
+
+type BaseFromKplerIndexSearchItem struct {
+	BaseFromKplerIndexId int `orm:"column(base_from_kpler_index_id);pk" gorm:"primaryKey"`
+	ClassifyId           int
+	ParentClassifyId     int
+	IndexCode            string
+	IndexName            string
+}
+
+// BatchCheckKplerEdbReq 指标数据结构体
+type BatchCheckKplerEdbReq struct {
+	Frequencies   string `description:"频度;枚举值:日度、周度、月度、季度、半年度、年度"`
+	Keyword       string `description:"关键字"`
+	ClassifyIds   string `description:"所选品种id列表"`
+	ListAll       bool   `form:"ListAll" json:"ListAll" description:"列表全选"`
+	TradeCodeList string `form:"TradeCodeList" json:"TradeCodeList" description:"全选为false时, 该数组为选中; 全选为true时, 该数组为不选的指标"`
+}
+
+// GetKplerItemList 模糊查询Kpler数据库指标列表
+func GetKplerItemList(condition string) (items []*BaseFromKplerIndexSearchItem, err error) {
+	o := global.DbMap[utils.DbNameIndex]
+	sql := "SELECT * FROM base_from_kpler_index  WHERE 1=1"
+	if condition != "" {
+		sql += condition
+	}
+	err = o.Raw(sql).Find(&items).Error
+	return
+}
+
+func GetKplerIndexDataByCode(indexCode string) (list []*BaseFromKplerData, err error) {
+	o := global.DbMap[utils.DbNameIndex]
+	sql := `SELECT * FROM base_from_kpler_data WHERE index_code=? `
+	err = o.Raw(sql, indexCode).Find(&list).Error
+	return
+}
+
+func GetBaseFromKplerIndexByIndexCode(indexCode string) (list *BaseFromKplerIndex, err error) {
+	o := global.DbMap[utils.DbNameIndex]
+	sql := ` SELECT * FROM base_from_kpler_index WHERE index_code=? `
+	err = o.Raw(sql, indexCode).First(&list).Error
+	return
+}
+
+type BaseFromKplerIndexType struct {
+	Type2 string `gorm:"column:type_2"`
+	Type3 string `gorm:"column:type_3"`
+}
+
+// Update 更新Kpler指标基础信息
+func (item *BaseFromKplerIndex) Update(cols []string) (err error) {
+	o := global.DbMap[utils.DbNameIndex]
+	err = o.Select(cols).Updates(item).Error
+	return
+}
+
+// EditKplerIndexInfoResp 新增指标的返回
+type EditKplerIndexInfoResp struct {
+	BaseFromKplerIndexId int    `description:"指标ID"`
+	IndexCode            string `description:"指标code"`
+}
+
+type KplerIndexSource2EdbReq struct {
+	EdbCode       string
+	EdbName       string
+	Frequency     string
+	Unit          string
+	ClassifyId    int
+	AdminId       int
+	AdminRealName string
+}
+
+func GetKplerFrequencyByClassifyId(classifyId int) (items []*GlFrequency, err error) {
+	o := global.DbMap[utils.DbNameIndex]
+	sql := ` SELECT frequency FROM base_from_kpler_index WHERE classify_id = ? `
+	sql += ` GROUP BY frequency ORDER BY frequency ASC `
+	err = o.Raw(sql, classifyId).Find(&items).Error
+	return
+}
+
+// GetKplerZoneById 根据区域ID获取区域信息
+func GetKplerZoneById(zoneId int) (item *BaseFromKplerZone, err error) {
+	o := global.DbMap[utils.DbNameIndex]
+	sql := `SELECT * FROM base_from_kpler_zone WHERE base_from_kpler_zone_id=? `
+	err = o.Raw(sql, zoneId).First(&item).Error
+	return
+}
+
+// GetKplerZoneByIds 根据区域ID列表获取区域信息
+func GetKplerZoneByIds(zoneIds []int) (items []*BaseFromKplerZone, err error) {
+	if len(zoneIds) == 0 {
+		return
+	}
+	o := global.DbMap[utils.DbNameIndex]
+	sql := `SELECT * FROM base_from_kpler_zone WHERE base_from_kpler_zone_id IN (` + utils.GetOrmInReplace(len(zoneIds)) + `) `
+	err = o.Raw(sql, zoneIds).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"`
+	CreateTime          time.Time `description:"创建时间"`
+	ModifyTime          time.Time `description:"修改时间"`
+}
+
+func GetBaseFromKplerZoneByKeyword(keyword string) (items []*BaseFromKplerZone, err error) {
+	o := global.DbMap[utils.DbNameIndex]
+	sql := `SELECT * FROM base_from_kpler_zone WHERE zone_name LIKE ? `
+	err = o.Raw(sql, "%"+keyword+"%").Find(&items).Error
+	return
+}
+
+// GetBaseFromKplerZoneByKeywordWithRelevance searches for zones with similarity-based sorting
+// It prioritizes exact matches, then prefix matches, then contains matches
+func GetBaseFromKplerZoneByKeywordWithRelevance(keyword string) (items []*BaseFromKplerZone, err error) {
+	o := global.DbMap[utils.DbNameIndex]
+	sql := `
+		SELECT * FROM base_from_kpler_zone 
+		WHERE zone_name LIKE ? 
+		ORDER BY 
+			CASE 
+				WHEN zone_name = ? THEN 1 
+				WHEN zone_name LIKE ? THEN 2 
+				ELSE 3 
+			END, 
+			zone_name ASC
+	`
+	err = o.Raw(sql, "%"+keyword+"%", keyword, keyword+"%").Find(&items).Error
+	return
+}
+
+type KplerSearchReq struct {
+	ProductIds []int `description:"产品ID"`
+	FromZoneIds []int `description:"来源区域ID,对应Location" ` 
+	ToZoneIds []int `description:"流向区域ID"`
+	Split string `description:"拆分类型"`
+	FlowDirection string `description:"流向,对应periodicity:export/import"`
+	Granularity string `description:"粒度: daily/weekly/monthly/yearly"`
+	Unit string `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 *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
+}
+
+func GetKplerIndexByIndexCode(indexCode string) (item *BaseFromKplerIndex, err error) {
+	o := global.DbMap[utils.DbNameIndex]
+	sql := ` SELECT * FROM base_from_kpler_index WHERE index_code=? `
+	err = o.Raw(sql, indexCode).First(&item).Error
+	return
+}
+
+type KplerSearchEdbLibResp struct {
+	Ret     int
+	Msg     string
+	ErrMsg  string
+	ErrCode string
+	Data    []*KplerIndexItem
+	Success bool `description:"true 执行成功,false 执行失败"`
+}
+
+type KplerIndexItem struct {
+	IndexCode string 
+	IndexName string 
+	Unit string 
+	Frequency string 
+	IndexData []KplerIndexDataItem 
+}
+
+type KplerIndexDataItem struct {
+	DataTime string
+	Value string 
+}

+ 126 - 0
routers/commentsRouter.go

@@ -2914,6 +2914,132 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:BaseFromKplerController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:BaseFromKplerController"],
+        beego.ControllerComments{
+            Method: "KplerBatchAdd",
+            Router: `/kpler/batch_add`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:BaseFromKplerController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:BaseFromKplerController"],
+        beego.ControllerComments{
+            Method: "KplerBatchSearch",
+            Router: `/kpler/batch_search`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:BaseFromKplerController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:BaseFromKplerController"],
+        beego.ControllerComments{
+            Method: "KplerClassify",
+            Router: `/kpler/classify`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:BaseFromKplerController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:BaseFromKplerController"],
+        beego.ControllerComments{
+            Method: "KplerIndexList",
+            Router: `/kpler/classify/index/list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:BaseFromKplerController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:BaseFromKplerController"],
+        beego.ControllerComments{
+            Method: "KplerClassifyTree",
+            Router: `/kpler/classify/tree`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:BaseFromKplerController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:BaseFromKplerController"],
+        beego.ControllerComments{
+            Method: "KplerAddCheck",
+            Router: `/kpler/edb_info/add_check`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:BaseFromKplerController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:BaseFromKplerController"],
+        beego.ControllerComments{
+            Method: "KplerNameCheck",
+            Router: `/kpler/edb_info/name_check`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:BaseFromKplerController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:BaseFromKplerController"],
+        beego.ControllerComments{
+            Method: "ExportKplerList",
+            Router: `/kpler/export`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:BaseFromKplerController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:BaseFromKplerController"],
+        beego.ControllerComments{
+            Method: "IndexAdd",
+            Router: `/kpler/index/add`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:BaseFromKplerController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:BaseFromKplerController"],
+        beego.ControllerComments{
+            Method: "KplerIndexData",
+            Router: `/kpler/index/data`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:BaseFromKplerController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:BaseFromKplerController"],
+        beego.ControllerComments{
+            Method: "Search",
+            Router: `/kpler/index/search`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:BaseFromKplerController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:BaseFromKplerController"],
+        beego.ControllerComments{
+            Method: "KplerSearchList",
+            Router: `/kpler/search_list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:BaseFromKplerController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:BaseFromKplerController"],
+        beego.ControllerComments{
+            Method: "KplerSingleData",
+            Router: `/kpler/single_data`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:BaseFromKplerController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:BaseFromKplerController"],
+        beego.ControllerComments{
+            Method: "KplerZone",
+            Router: `/kpler/zone`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:BaseFromLyClassifyController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:BaseFromLyClassifyController"],
         beego.ControllerComments{
             Method: "LyClassifyList",

+ 1 - 0
routers/router.go

@@ -210,6 +210,7 @@ func init() {
 				&data_manage.BaseFromRadishResearchController{},
 				&data_manage.EdbInspectionController{},
 				&data_manage.EdbInspectionMessageController{},
+				&data_manage.BaseFromKplerController{},
 			),
 		),
 		web.NSNamespace("/my_chart",

+ 131 - 0
services/data/base_from_kpler.go

@@ -0,0 +1,131 @@
+package data
+
+import (
+	"encoding/json"
+	"eta/eta_api/models/data_manage"
+	"eta/eta_api/utils"
+	"fmt"
+)
+
+// KplerIndexSource2Edb 新增Kpler数据源到指标库
+func KplerIndexSource2Edb(req data_manage.KplerIndexSource2EdbReq, lang string) (edb *data_manage.EdbInfo, err error, errMsg string, skip bool) {
+	if req.EdbCode == "" {
+		err = fmt.Errorf("指标ID为空")
+		return
+	}
+	defer func() {
+		if err != nil {
+			tips := fmt.Sprintf("KplerIndexSource2Edb新增失败, Err: %s", err.Error())
+			fmt.Println(tips)
+			utils.FileLog.Info(tips)
+		}
+	}()
+	source := utils.DATA_SOURCE_KPLER
+
+	// 是否新增过指标
+	exist, e := data_manage.GetEdbInfoByEdbCode(source, req.EdbCode)
+	if e != nil && !utils.IsErrNoRow(e) {
+		err = fmt.Errorf("获取指标是否存在失败, err: %s", e.Error())
+		return
+	}
+	if exist != nil && exist.EdbInfoId > 0 {
+		skip = true
+		return
+	}
+
+	// 开始结束时间
+	var startDate, endDate string
+
+	// 新增指标库
+	edbInfo, e, msg, _ := EdbInfoAdd(source, utils.DATA_SUB_SOURCE_EDB, req.ClassifyId, req.EdbCode, req.EdbName, req.Frequency, req.Unit, startDate, endDate, req.AdminId, req.AdminRealName, lang)
+	if e != nil {
+		errMsg = msg
+		err = fmt.Errorf("EdbInfo: 新增指标失败, err: %s", e.Error())
+		return
+	}
+
+	edb = edbInfo
+
+	return
+} 
+
+
+func GetEdbDataKpler(req data_manage.KplerSearchReq, productNames string, fromZoneNames string, toZoneNames string) (indexes []*data_manage.KplerIndexItem, err error) {
+	param := make(map[string]interface{})
+	param["ProductNames"] = productNames
+	param["FromZoneIds"] = req.FromZoneIds
+	param["FromZoneNames"] = fromZoneNames
+	param["ToZoneIds"] = req.ToZoneIds
+	param["ToZoneNames"] = toZoneNames
+	param["Split"] = req.Split
+	param["FlowDirection"] = req.FlowDirection
+	param["Granularity"] = req.Granularity
+	param["Unit"] = req.Unit
+	uri := `kpler/edb_data`
+	resp, e := postKplerEdbData(param, uri)
+	if e != nil {
+		err = fmt.Errorf("postKplerEdbData, %v", e)
+		return
+	}
+	if resp.Ret == 200 {
+		indexes = resp.Data
+	}
+	return
+}
+
+func AddKplerIndex(req data_manage.KplerSearchReq, productNames string, fromZoneNames string, toZoneNames string) (err error) {
+	param := make(map[string]interface{})
+	param["ProductNames"] = productNames
+	param["FromZoneIds"] = req.FromZoneIds
+	param["FromZoneNames"] = fromZoneNames
+	param["ToZoneIds"] = req.ToZoneIds
+	param["ToZoneNames"] = toZoneNames
+	param["Split"] = req.Split
+	param["FlowDirection"] = req.FlowDirection
+	param["Granularity"] = req.Granularity
+	param["Unit"] = req.Unit
+	uri := `kpler/index_add`
+	resp, e := postKplerEdbData(param, uri)
+	if e != nil {
+		err = fmt.Errorf("postKplerEdbData, %v", e)
+		return
+	}
+	if resp.Ret != 200 {
+		err = fmt.Errorf("新增指标失败, %v", resp.ErrMsg)
+		return
+	}
+	return
+}
+
+// postKplerEdbData 刷新指标数据
+func postKplerEdbData(param map[string]interface{}, urlStr string) (resp *data_manage.KplerSearchEdbLibResp, err error) {
+	postUrl := utils.EDB_LIB_URL + urlStr
+	postData, err := json.Marshal(param)
+	if err != nil {
+		return
+	}
+	result, err := HttpPost(postUrl, string(postData), utils.ZhLangVersion, "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
+}
+
+
+
+// GetMenuTreeRecursive 递归菜单树
+func GetKplerClassifyTreeRecursive(list []*data_manage.BaseFromKplerClassifyItems, parentId int) []*data_manage.BaseFromKplerClassifyItems {
+	res := make([]*data_manage.BaseFromKplerClassifyItems, 0)
+	for _, v := range list {
+		if v.ParentId == parentId {
+			v.Children = GetKplerClassifyTreeRecursive(list, v.ClassifyId)
+			res = append(res, v)
+		}
+	}
+	return res
+}

+ 1 - 0
utils/constants.go

@@ -196,6 +196,7 @@ const (
 	DATA_SOURCE_AI_PREDICT_MODEL                     = 103      // AI预测模型(edb_source里实际不存在这个,ES里面的为103)
 	DATA_SOURCE_PURANG                               = 104      // 普兰金融
 	DATA_SOURCE_RADISH_RESEARCH                      = 105      // 萝卜投研
+	DATA_SOURCE_KPLER                                = 106      // Kpler数据
 )
 
 // 数据刷新频率