Quellcode durchsuchen

Merge remote-tracking branch 'origin/debug' into debug

zwxi vor 9 Monaten
Ursprung
Commit
b561d17377
34 geänderte Dateien mit 2782 neuen und 359 gelöschten Zeilen
  1. 50 0
      controllers/data_manage/base_from_ly_classify_controller.go
  2. 537 0
      controllers/data_manage/base_from_ly_index_controller.go
  3. 12 0
      controllers/data_manage/chart_common.go
  4. 1 35
      controllers/data_manage/chart_info.go
  5. 46 0
      controllers/data_manage/edb_info.go
  6. 20 0
      controllers/data_manage/eia_steo.go
  7. 6 1
      controllers/data_manage/manual_edb.go
  8. 581 60
      controllers/data_manage/range_analysis/chart_info.go
  9. 60 29
      controllers/data_manage/sci_hq_data.go
  10. 83 43
      controllers/target.go
  11. 1 0
      models/data_manage/base_from_eia_stero.go
  12. 48 0
      models/data_manage/base_from_ly_classify.go
  13. 87 0
      models/data_manage/base_from_ly_data.go
  14. 244 0
      models/data_manage/base_from_ly_index.go
  15. 2 2
      models/data_manage/base_from_sci_hq_classify.go
  16. 32 29
      models/data_manage/base_from_sci_hq_index.go
  17. 154 3
      models/data_manage/chart_info_range_analysis.go
  18. 7 2
      models/data_manage/edb_data_base.go
  19. 10 0
      models/data_manage/edb_data_sci_hq.go
  20. 2 2
      models/data_manage/factor_edb_series_calculate_data_qjjs.go
  21. 1 1
      models/data_manage/multiple_graph_config_edb_mapping.go
  22. 19 1
      models/target.go
  23. 91 1
      routers/commentsRouter.go
  24. 2 0
      routers/router.go
  25. 6 0
      services/data/base_edb_lib.go
  26. 3 1
      services/data/base_from_eia_steo.go
  27. 47 0
      services/data/base_from_ly_classify_service.go
  28. 222 0
      services/data/base_from_ly_index_service.go
  29. 7 7
      services/data/base_from_sci_hq.go
  30. 10 0
      services/data/edb_classify.go
  31. 1 0
      services/data/edb_info.go
  32. 368 142
      services/data/range_analysis/chart_info.go
  33. 11 0
      utils/common.go
  34. 11 0
      utils/constants.go

+ 50 - 0
controllers/data_manage/base_from_ly_classify_controller.go

@@ -0,0 +1,50 @@
+// Package data_manage
+// @Author gmy 2024/8/12 14:32:00
+package data_manage
+
+import (
+	"eta/eta_api/controllers"
+	"eta/eta_api/models"
+	"eta/eta_api/services/data"
+)
+
+type BaseFromLyClassifyController struct {
+	controllers.BaseAuthController
+}
+
+// LyClassifyList 获取分类列表
+// @Description 包含分类下的指标名称
+// @Success 200 {object} []data_manage.BaseFromLyClassifyAndIndexInfo
+// @router /ly/classify/list [get]
+func (this *BaseFromLyClassifyController) LyClassifyList() {
+	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
+	}
+	// 获取分类列表
+	lyClassifyList, err := data.LyClassifyList()
+	if err != nil {
+		br.Msg = "获取分类列表失败"
+		br.ErrMsg = "获取分类列表失败,Err:" + err.Error()
+		return
+	}
+
+	br.Data = lyClassifyList
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+}

+ 537 - 0
controllers/data_manage/base_from_ly_index_controller.go

@@ -0,0 +1,537 @@
+// Package data_manage
+// @Author gmy 2024/8/12 14:31:00
+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"
+	"github.com/tealeg/xlsx"
+	"os"
+	"path/filepath"
+	"strconv"
+	"strings"
+	"time"
+)
+
+type BaseFromLyIndexController struct {
+	controllers.BaseAuthController
+}
+
+const (
+	codeMax    = 30 // 指标编码最大数量
+	dataSource = "粮油商务网"
+)
+
+// LyIndexList
+// @Title 获取指标列表
+// @Description 获取指标列表
+// @Param   searchParam	 query   string     false        "搜索参数"
+// @Param   PageSize    query   int     true        "每页数据条数"
+// @Param   CurrentIndex    query   int     true        "当前页页码,从1开始"
+// @Success 200 {object} []data_manage.BaseFromLyIndexPage
+// @router /ly/index/list [get]
+func (this *BaseFromLyIndexController) LyIndexList() {
+	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
+	}
+
+	pageSize, _ := this.GetInt("PageSize")
+	currentIndex, _ := this.GetInt("CurrentIndex")
+	searchParam := this.GetString("SearchParam")
+	classifyId := this.GetString("ClassifyId")
+
+	if pageSize <= 0 {
+		pageSize = utils.PageSize20
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+
+	// 获取指标列表
+	indexList, err := data.GetIndexPage(classifyId, searchParam, currentIndex, pageSize)
+	if err != nil {
+		br.Msg = "获取指标列表失败"
+		br.ErrMsg = "获取指标列表失败,Err:" + err.Error()
+		return
+	}
+
+	br.Data = indexList
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+}
+
+// LyIndexDataList
+// @Title 获取指标对应的数据列表
+// @Description 获取指标对应的数据列表
+// @Param   indexId     query   int     true        "指标ID"
+// @Param   PageSize    query   int     true        "每页数据条数"
+// @Param   CurrentIndex    query   int     true        "当前页页码,从1开始"
+// @Success 200 {object} data_manage.BaseFromLyDataPage
+// @router /ly/index/data/list [get]
+func (this *BaseFromLyIndexController) LyIndexDataList() {
+	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
+	}
+
+	// 获取指标数据列表
+	indexId, err := this.GetInt("IndexId")
+	if err != nil {
+		br.Msg = "获取指标ID失败"
+		br.ErrMsg = "获取指标ID失败,Err:" + err.Error()
+		return
+	}
+	pageSize, _ := this.GetInt("PageSize")
+	currentIndex, _ := this.GetInt("CurrentIndex")
+
+	if pageSize <= 0 {
+		pageSize = utils.PageSize20
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+
+	indexDataList, err := data.GetIndexDataPage(indexId, currentIndex, pageSize)
+	if err != nil {
+		br.Msg = "获取指标数据列表失败"
+		br.ErrMsg = "获取指标数据列表失败,Err:" + err.Error()
+		return
+	}
+
+	br.Data = indexDataList
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+}
+
+// LyIndexAddValidate
+// @Title 新增加入到指标库校验
+// @Description 新增加入到指标库校验
+// @Param   req    body   data_manage.BaseFromLyIndexBatchAddCheckReq     true        "请求参数"
+// @Success 200 {object} []data_manage.IndexCheckData
+// @router /ly/index/add/validate [post]
+func (this *BaseFromLyIndexController) LyIndexAddValidate() {
+	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.BaseFromLyIndexBatchAddCheckReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + e.Error()
+		return
+	}
+
+	codeLen := len(req.IndexCodes)
+	if codeLen > codeMax {
+		br.Msg = "批量添加指标数量不得超过" + strconv.Itoa(codeMax) + "个"
+		br.ErrMsg = "批量添加指标数量不得超过" + strconv.Itoa(codeMax) + "个"
+		return
+	}
+
+	// 校验指标编码是否存在
+	addValidate, err := data.LyIndexAddValidate(req.IndexCodes)
+	if err != nil {
+		return
+	}
+	br.Data = addValidate
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+// LyIndexAdd
+// @Title 指标添加到指标库
+// @Description 指标添加到指标库
+// @Param   req    body   []data_manage.AddEdbInfoReq     true        "请求参数"
+// @Success 200 string "操作成功"
+// @router /ly/index/add [post]
+func (this *BaseFromLyIndexController) LyIndexAdd() {
+	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_LY_" + 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) > codeMax {
+		br.Msg = "批量添加指标数量不得超过" + strconv.Itoa(codeMax) + "个"
+		return
+	}
+
+	indexNames := make([]string, 0)
+	resp := make([]*data_manage.NameCheckResult, 0)
+	for _, index := range req {
+		index.EdbCode = strings.TrimSpace(index.EdbCode)
+		if index.EdbCode == "" {
+			br.Msg = "指标ID不可为空"
+			return
+		}
+		index.EdbName = strings.TrimSpace(index.EdbName)
+		if index.EdbName == "" {
+			br.Msg = "请输入指标名称"
+			return
+		}
+		index.Frequency = strings.TrimSpace(index.Frequency)
+		if index.Frequency == "" {
+			br.Msg = "请选择频度"
+			return
+		}
+		index.Unit = strings.TrimSpace(index.Unit)
+		if index.Unit == "" {
+			br.Msg = "请输入单位"
+			return
+		}
+		if index.ClassifyId <= 0 {
+			br.Msg = "请选择分类"
+			return
+		}
+		indexNames = append(indexNames, index.EdbName)
+		resp = append(resp, &data_manage.NameCheckResult{
+			IndexCode: index.EdbCode,
+			IndexName: index.EdbName,
+			Exist:     false,
+		})
+	}
+
+	// 指标名称重复校验
+	nameCheck, err := data.LyIndexNameCheck(indexNames, resp)
+	if err != nil {
+		br.Msg = err.Error()
+		br.ErrMsg = err.Error()
+		return
+	}
+	for _, v := range nameCheck {
+		if v.Exist {
+			br.Msg = "指标名称重复"
+			br.Data = nameCheck
+			br.Ret = 200
+			br.Success = true
+			return
+		}
+	}
+
+	for _, v := range req {
+		var r data.LyIndexAddReq
+		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.LyIndexAdd(r, this.Lang)
+		if e != nil {
+			br.Msg = "操作失败"
+			if errMsg != "" {
+				br.Msg = errMsg
+			}
+			br.ErrMsg = e.Error()
+			return
+		}
+		if skip {
+			continue
+		}
+
+		// todo 下面两段代码能否抽离出来???
+		// 试用平台更新用户累计新增指标数
+		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
+}
+
+// LyIndexDataExport
+// @Title 导出指标数据
+// @Description 导出指标数据
+// @Param  IndexCode     query   string     false        "指标编码"
+// @Param  ClassifyId     query   int     false        "分类ID"
+// @Success 200 string "操作成功"
+// @router /ly/index/data/export [get]
+func (this *BaseFromLyIndexController) LyIndexDataExport() {
+	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")   //指标唯一编码
+
+	//userId := sysUser.AdminId
+	//超管账号可以查看分类下的所有频度数据
+	/*if sysUser.RoleTypeCode == utils.ROLE_TYPE_CODE_ADMIN {
+		userId = 0
+	}*/
+	//获取账户所拥有权限的分类id集合
+	/*classifyIdStrList, err := data.GetEdbClassifyListByAdminId(int64(userId))
+	if err != nil {
+		br.Msg = "获取分类数据失败"
+		return
+	}*/
+
+	dir, _ := os.Executable()
+	exPath := filepath.Dir(dir)
+
+	downLoadFilePath := exPath + "/" + time.Now().Format(utils.FormatDateTimeUnSpace) + ".xlsx"
+	xlsxFile := xlsx.NewFile()
+	frequencies, err := data_manage.GetLyIndexFrequency(classifyId)
+	if err != nil {
+		br.Msg = "查询频度失败"
+		br.ErrMsg = "查询频度失败"
+		return
+	}
+
+	fileName := `粮油商务网`
+	if classifyId > 0 && indexCode == "" {
+		lyClassify, err := data_manage.GetLyClassifyById(classifyId)
+		if err != nil {
+			return
+		}
+		fileName = lyClassify.ClassifyName
+	}
+	if frequencies == 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("")
+	}
+
+	for _, frequency := range frequencies {
+		lyIndices, err := data_manage.GetLyIndexByCodeAndClassify(indexCode, classifyId, frequency)
+		if err != nil {
+			return
+		}
+		var sheet *xlsx.Sheet
+		if len(lyIndices) > 0 {
+			sheet, err = xlsxFile.AddSheet(*frequency)
+			if err != nil {
+				br.Msg = "新增Sheet失败"
+				br.ErrMsg = "新增Sheet失败,Err:" + err.Error()
+				return
+			}
+		} else {
+			continue
+		}
+
+		if indexCode != "" {
+			fileName = lyIndices[0].IndexName
+		}
+
+		//获取指标数据
+		rowSecName := sheet.AddRow()
+		celSecName := rowSecName.AddCell()
+		celSecName.SetValue("指标名称")
+		rowFrequency := sheet.AddRow()
+		celFrequency := rowFrequency.AddCell()
+		celFrequency.SetValue("频率")
+		rowUnit := sheet.AddRow()
+		celUnit := rowUnit.AddCell()
+		celUnit.SetValue("单位")
+		rowModifyDate := sheet.AddRow()
+		rowModifyCell := rowModifyDate.AddCell()
+		rowModifyCell.SetValue("更新时间")
+
+		dataMap := make(map[string]map[string]*data_manage.BaseFromLyData)
+		var tradeCodeList []string
+		for _, v := range lyIndices {
+			cellSenName := rowSecName.AddCell()
+			cellSenName.SetValue(v.IndexName)
+			celFrequency := rowFrequency.AddCell()
+			celFrequency.SetValue(v.Frequency)
+			celUnit := rowUnit.AddCell()
+			celUnit.SetValue(v.Unit)
+			rowModifyCell := rowModifyDate.AddCell()
+			rowModifyCell.SetValue(v.ModifyTime)
+			tradeCodeList = append(tradeCodeList, v.IndexCode)
+
+			var lyDataList []*data_manage.BaseFromLyData
+			lyDataList, err = data_manage.GetBaseFromLyDataByIndexCode(v.IndexCode)
+			if err != nil && err.Error() != utils.ErrNoRow() {
+				br.ErrMsg = "GetBaseFromLyDataByIndexCode,Err:" + err.Error()
+				br.Msg = "获取数据失败"
+				return
+			}
+			for _, item := range lyDataList {
+				if dataMap[item.IndexCode] == nil {
+					dataMap[item.IndexCode] = make(map[string]*data_manage.BaseFromLyData)
+				}
+				dataMap[item.IndexCode][item.DataTime] = item
+			}
+		}
+
+		tradeCodeStr := strings.Join(tradeCodeList, "','")
+		tradeCodeStr = "'" + tradeCodeStr + "'"
+		dataTimeList, err := data_manage.GetLyDataListByIndexCodes(tradeCodeStr)
+		if err != nil {
+			br.Msg = "获取数据失败"
+			br.ErrMsg = "获取数据失败,Err:" + err.Error()
+			return
+		}
+		for _, dataTime := range dataTimeList {
+			rowData := sheet.AddRow()
+			celDate := rowData.AddCell()
+			celDate.SetValue(dataTime)
+
+			for _, m := range lyIndices {
+				celData := rowData.AddCell()
+				if dataMap[m.IndexCode][dataTime] != nil {
+					celData.SetValue(dataMap[m.IndexCode][dataTime].Value)
+				}
+			}
+		}
+	}
+
+	err = xlsxFile.Save(downLoadFilePath)
+	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("")
+		err = xlsxFile.Save(downLoadFilePath)
+		if err != nil {
+			br.Msg = "保存文件失败"
+			br.ErrMsg = "保存文件失败"
+			return
+		}
+	}
+
+	fileName += time.Now().Format("06.01.02") + `.xlsx` //文件名称
+	this.Ctx.Output.Download(downLoadFilePath, fileName)
+	defer func() {
+		os.Remove(downLoadFilePath)
+	}()
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "success"
+}

+ 12 - 0
controllers/data_manage/chart_common.go

@@ -7,6 +7,7 @@ import (
 	"eta/eta_api/controllers/data_manage/future_good"
 	"eta/eta_api/controllers/data_manage/line_equation"
 	"eta/eta_api/controllers/data_manage/line_feature"
+	"eta/eta_api/controllers/data_manage/range_analysis"
 	"eta/eta_api/models"
 	"eta/eta_api/models/data_manage"
 	"eta/eta_api/models/system"
@@ -167,6 +168,17 @@ func (this *ChartInfoController) CommonChartInfoDetailFromUniqueCode() {
 		br.Success = true
 		br.Msg = "获取成功"
 		br.Data = resp
+	case utils.CHART_SOURCE_RANGE_ANALYSIS:
+		resp, isOk, msg, errMsg := range_analysis.GetChartInfoDetailFromUniqueCode(chartInfo, isCache, sysUser)
+		if !isOk {
+			br.Msg = msg
+			br.ErrMsg = errMsg
+			return
+		}
+		br.Ret = 200
+		br.Success = true
+		br.Msg = "获取成功"
+		br.Data = resp
 	default:
 		br.Msg = "错误的图表"
 		br.ErrMsg = "错误的图表"

+ 1 - 35
controllers/data_manage/chart_info.go

@@ -18,7 +18,6 @@ import (
 	"github.com/rdlucklib/rdluck_tools/paging"
 	"os"
 	"os/exec"
-	"sort"
 	"strconv"
 	"strings"
 	"time"
@@ -92,40 +91,7 @@ func (this *ChartInfoController) ChartInfoSave() {
 		req.Calendar = "公历"
 	}
 
-	var edbInfoIdArr []int
-	edbList := make([]*data_manage.EdbInfo, 0)
-
-	for _, v := range req.ChartEdbInfoList {
-		edbInfo, err := data_manage.GetEdbInfoById(v.EdbInfoId)
-		if err != nil {
-			if err.Error() == utils.ErrNoRow() {
-				br.Msg = "图表不存在!"
-				br.ErrMsg = "图表不存在,ChartInfoId:" + strconv.Itoa(v.EdbInfoId)
-				return
-			} else {
-				br.Msg = "获取图表信息失败!"
-				br.ErrMsg = "获取图表的指标信息失败,Err:" + err.Error()
-				return
-			}
-		}
-
-		if edbInfo == nil {
-			br.Msg = "指标不存在!"
-			br.ErrMsg = "指标不存在,ChartInfoId:" + strconv.Itoa(v.EdbInfoId)
-			return
-		}
-
-		edbInfoIdArr = append(edbInfoIdArr, v.EdbInfoId)
-		edbInfo.EdbNameSource = edbInfo.EdbName
-		edbList = append(edbList, edbInfo)
-	}
-	sort.Ints(edbInfoIdArr)
-	var edbInfoIdArrStr []string
-	for _, v := range edbInfoIdArr {
-		edbInfoIdArrStr = append(edbInfoIdArrStr, strconv.Itoa(v))
-	}
-	edbInfoIdStr := strings.Join(edbInfoIdArrStr, ",")
-	err = data_manage.ModifyChartInfoAndMapping(edbInfoIdStr, &req, chartItem.ChartType)
+	err = data_manage.ModifyChartInfoAndMapping(chartItem.EdbInfoIds, &req, chartItem.ChartType)
 	if err != nil {
 		br.Msg = "保存失败"
 		br.ErrMsg = "保存失败,Err:" + err.Error()

+ 46 - 0
controllers/data_manage/edb_info.go

@@ -1804,6 +1804,52 @@ func (this *EdbInfoController) EdbInfoSearch() {
 				searchItem.Unit = "元/吨"
 				searchItem.EdbName = indexInfo.IndexName
 			}
+		} else if source == utils.DATA_SOURCE_SCI_HQ {
+			dataItems, err := data_manage.GetEdbDataAllByEdbCode(edbCode, source, subSource, utils.EDB_DATA_LIMIT)
+			if err != nil && err.Error() != utils.ErrNoRow() {
+				br.Msg = "获取失败"
+				br.ErrMsg = "获取SCIHQ已存在信息失败,Err:" + err.Error()
+				return
+			}
+
+			fmt.Println("dataItems:", len(dataItems))
+			if len(dataItems) > 0 {
+				searchItem.EdbCode = edbCode
+				minDate, maxDate, err := data_manage.GetEdbDataSciHqMaxAndMinDate(edbCode)
+				if err != nil {
+					br.Msg = "获取失败"
+					br.ErrMsg = "获取SCIHQ日期信息失败,Err:" + err.Error()
+					return
+				}
+				searchItem.DataList = dataItems
+				searchItem.StartDate = minDate
+				searchItem.EndDate = maxDate
+			} else {
+				respItem, err := data.AddEdbData(source, edbCode, frequency)
+				if err != nil {
+					br.Msg = "获取失败"
+					br.ErrMsg = "获取失败,Err:" + err.Error()
+					return
+				}
+				if respItem.Ret != 200 {
+					br.Msg = "未搜索到该指标"
+					br.ErrMsg = respItem.ErrMsg + ";EdbCode:" + edbCode
+					return
+				}
+				isAdd = true
+			}
+			//获取指标信息
+			sciHqInfo, err := data_manage.GetSciHqIndexByIndexCode(edbCode)
+			if err != nil && err.Error() != utils.ErrNoRow() {
+				br.Msg = "获取失败"
+				br.ErrMsg = "获取SciHq指标详情失败,Err:" + err.Error()
+				return
+			}
+			if sciHqInfo != nil {
+				searchItem.Frequency = sciHqInfo.Frequency
+				searchItem.Unit = sciHqInfo.Unit
+				searchItem.EdbName = sciHqInfo.IndexName
+			}
 		} else if source == utils.DATA_SOURCE_OILCHEM { //隆众资讯
 			dataItems, err := data_manage.GetEdbDataAllByEdbCode(edbCode, source, subSource, utils.EDB_DATA_LIMIT)
 			if err != nil && err.Error() != utils.ErrNoRow() {

+ 20 - 0
controllers/data_manage/eia_steo.go

@@ -136,6 +136,20 @@ func (this *EdbInfoController) EiaSteoData() {
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
 	}
+	indexCodes := make([]string, 0)
+	for _, v := range indexList {
+		indexCodes = append(indexCodes, v.IndexCode)
+	}
+	edbinfoList, err := data_manage.GetEdbInfoByEdbCodeList(utils.DATA_SOURCE_EIA_STEO, indexCodes)
+	if err != nil {
+		br.Msg = "获取数据失败"
+		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+		return
+	}
+	existEdbInfo := make(map[string]int)
+	for _, v := range edbinfoList {
+		existEdbInfo[v.EdbCode] = v.EdbInfoId
+	}
 	resultList := make([]data_manage.EiaSteoIndexListResp, 0)
 	for _, v := range indexList {
 
@@ -149,6 +163,7 @@ func (this *EdbInfoController) EiaSteoData() {
 			IndexCode:                 v.IndexCode,
 			IndexName:                 indexName,
 			//IndexNameOriginal:          v.IndexNameOriginal,
+			EdbInfoId:  existEdbInfo[v.IndexCode],
 			Unit:       v.Unit,
 			Frequency:  v.Frequency,
 			StartDate:  v.StartDate.Format(utils.FormatDate),
@@ -160,6 +175,11 @@ func (this *EdbInfoController) EiaSteoData() {
 		}
 
 		total, err := data_manage.GetEiaSteoIndexDataCount(v.IndexCode)
+		if err != nil {
+			br.Msg = "获取数据失败"
+			br.ErrMsg = "获取指标统计数据失败,Err:" + err.Error()
+			return
+		}
 		page := paging.GetPaging(currentIndex, pageSize, total)
 
 		dataList, err := data_manage.GetEiaSteoIndexDataList(v.IndexCode, startSize, pageSize)

+ 6 - 1
controllers/data_manage/manual_edb.go

@@ -330,6 +330,9 @@ func (c *ManualEdbController) EdbList() {
 	var condition string
 	var pars []interface{}
 
+	// 权限用户id
+	permissionUserId := sysUser.AdminId
+
 	//超管账号可以查看分类下的所有频度数据
 	if sysUser.RoleTypeCode != utils.ROLE_TYPE_CODE_ADMIN {
 		classifyIdList, err := data.GetUserManualClassifyIdList(sysUser.AdminId)
@@ -344,6 +347,8 @@ func (c *ManualEdbController) EdbList() {
 			pars = append(pars, classifyIdList)
 		}
 
+	} else {
+		permissionUserId = 0
 	}
 
 	// 关键词
@@ -359,7 +364,7 @@ func (c *ManualEdbController) EdbList() {
 	// 所属分类
 	if classifyId > 0 {
 		// 获取有用权限的分类
-		classifyList, err := models.GetEdbdataClassify(int64(userId))
+		classifyList, err := models.GetEdbdataClassify(int64(permissionUserId))
 		if err != nil {
 			return
 		}

+ 581 - 60
controllers/data_manage/range_analysis/chart_info.go

@@ -5,6 +5,7 @@ import (
 	"eta/eta_api/controllers"
 	"eta/eta_api/models"
 	"eta/eta_api/models/data_manage"
+	"eta/eta_api/models/data_manage/chart_theme"
 	"eta/eta_api/models/system"
 	"eta/eta_api/services/data"
 	"eta/eta_api/services/data/data_manage_permission"
@@ -85,7 +86,14 @@ func (this *RangeChartChartInfoController) Preview() {
 	chartInfo := new(data_manage.ChartInfoView)
 	chartInfo.ChartType = 1
 	chartInfo.Source = utils.CHART_SOURCE_RANGE_ANALYSIS
-
+	chartTheme, err := chart_theme.GetSystemChartTheme(chartInfo.ChartType)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取图表主题失败, Err:" + err.Error()
+		return
+	}
+	chartInfo.ChartThemeId = chartTheme.ChartThemeId
+	chartInfo.ChartThemeStyle = chartTheme.Config
 	// 获取图表x轴y轴
 	edbList, xEdbIdValue, dataResp, e := rangeServ.GetChartDataByEdbInfoList(0, req.DateType, req.StartYear, req.StartDate, req.EndDate, edbInfoMappingList, &req.ExtraConfig)
 	if e != nil {
@@ -93,7 +101,6 @@ func (this *RangeChartChartInfoController) Preview() {
 		br.ErrMsg = "获取区间计算图表, 图表计算值失败, Err:" + e.Error()
 		return
 	}
-
 	//添加配置信息
 	if req.ExtraConfig.MultipleGraphConfigId == 0 {
 		multipleGraphConfig := &data_manage.MultipleGraphConfig{
@@ -163,7 +170,9 @@ func (this *RangeChartChartInfoController) Add() {
 		br.ErrMsg = "参数解析失败,Err:" + err.Error()
 		return
 	}
-
+	if req.DateType == 0 {
+		req.DateType = 3
+	}
 	chartInfo, err, errMsg, isSendEmail := rangeServ.AddChartInfo(req, utils.CHART_SOURCE_RANGE_ANALYSIS, sysUser, this.Lang)
 	if err != nil {
 		br.Msg = "保存失败"
@@ -409,8 +418,6 @@ func (this *RangeChartChartInfoController) Detail() {
 	chartInfo.IsEdit = data.CheckOpChartPermission(sysUser, chartInfo.SysUserId, true)
 	//判断是否需要展示英文标识
 	chartInfo.IsEnChart = data.CheckIsEnChart(chartInfo.ChartNameEn, edbList[0:1], chartInfo.Source, chartInfo.ChartType)
-	// todo 中英文处理
-	chartInfo.UnitEn = extraConfig.DataConvertConf.EnUnit
 
 	sourceNameList, sourceNameEnList := data.GetEdbSourceByEdbInfoIdList(edbList)
 	chartInfo.ChartSource = strings.Join(sourceNameList, ",")
@@ -610,11 +617,7 @@ func (this *RangeChartChartInfoController) DetailFromUniqueCode() {
 		br.ErrMsg = errMsg
 		return
 	}
-	if !isOk {
-		br.Msg = msg
-		br.ErrMsg = errMsg
-		return
-	}
+
 	br.Ret = 200
 	br.Success = true
 	br.Msg = "获取成功"
@@ -917,7 +920,16 @@ func (this *RangeChartChartInfoController) List() {
 		condition += " AND chart_classify_id IN(" + chartClassifyId + ") "
 	}
 	if keyword != "" {
-		condition += ` AND  ( chart_name LIKE '%` + keyword + `%' )`
+		//将关键词按照空格分割
+		keywords := strings.Split(keyword, " ")
+		condition += ` AND  ( chart_name LIKE '%` + keywords[0] + `%' `
+		for k, key := range keywords {
+			if k == 0 {
+				continue
+			}
+			condition += ` OR chart_name LIKE '%` + key + `%' `
+		}
+		condition += ` )`
 	}
 
 	//只看我的
@@ -1289,23 +1301,23 @@ func (this *RangeChartChartInfoController) MultipleGraphConfigSaveEdb() {
 	defer func() {
 		_ = utils.Rc.Delete(cacheKey)
 	}()
-	edbInfoIds := make([]int, 0)
+	fromEdbInfoIds := make([]int, 0)
 	for _, v := range req.EdbInfoList {
-		edbInfoIds = append(edbInfoIds, v.FromEdbInfoId)
+		fromEdbInfoIds = append(fromEdbInfoIds, v.FromEdbInfoId)
 	}
-	mappingList, err := data_manage.GetChartEdbMappingListByEdbInfoIdList(edbInfoIds)
+	fromEdbInfoMappingList, err := data_manage.GetChartEdbMappingListByEdbInfoIdList(fromEdbInfoIds)
 	if err != nil {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取图表,指标信息失败,Err:" + err.Error()
 		return
 	}
-	edbInfoMap := make(map[int]*data_manage.ChartEdbInfoMapping, 0)
-	for _, v := range mappingList {
-		edbInfoMap[v.EdbInfoId] = v
+	fromEdbInfoMap := make(map[int]*data_manage.ChartEdbInfoMapping, 0)
+	for _, v := range fromEdbInfoMappingList {
+		fromEdbInfoMap[v.EdbInfoId] = v
 	}
 
 	for _, v := range req.EdbInfoList {
-		if _, ok := edbInfoMap[v.FromEdbInfoId]; !ok {
+		if _, ok := fromEdbInfoMap[v.FromEdbInfoId]; !ok {
 			br.Msg = "指标信息不存在"
 			br.ErrMsg = "指标信息不存在,EdbInfoId:" + strconv.Itoa(v.FromEdbInfoId)
 			br.IsSendEmail = false
@@ -1313,15 +1325,28 @@ func (this *RangeChartChartInfoController) MultipleGraphConfigSaveEdb() {
 		}
 	}
 	// 区间计算图表配置校验
-	/*var extraConfig string
-	extraConfigByte, err := json.Marshal(req.ExtraConfig)
+	extraConfig := req.ExtraConfig
+	// 区间计算图表配置校验
+	var config data_manage.ChartRangeAnalysisExtraConf
+	if req.ExtraConfig == `` {
+		br.Msg = "请输入配置信息"
+		return
+	}
+	err = json.Unmarshal([]byte(req.ExtraConfig), &config)
 	if err != nil {
-		br.Msg = "配置信息错误"
-		br.ErrMsg = "配置信息错误, Err: " + err.Error()
+		br.Msg = "配置信息格式错误"
+		br.ErrMsg = "配置信息格式错误,Err:" + err.Error()
 		return
-	}*/
-	extraConfig := req.ExtraConfig
-	// todo 校验配置合法性
+	}
+
+	err, errMsg, isSendEmail := rangeServ.CheckChartRangeExtraConfig(config)
+	if err != nil {
+		br.Msg = "配置信息校验失败"
+		br.ErrMsg = errMsg
+		br.IsSendEmail = isSendEmail
+		return
+	}
+
 	multipleGraphConfigEdbMappingList, err := data_manage.GetMultipleGraphConfigEdbMappingListByIdAndSource(req.MultipleGraphConfigId, utils.CHART_SOURCE_RANGE_ANALYSIS)
 	if err != nil {
 		br.Msg = `保存失败`
@@ -1352,7 +1377,7 @@ func (this *RangeChartChartInfoController) MultipleGraphConfigSaveEdb() {
 		// 说明指标还在,没有被删除
 		for _, v := range oldEdbCalculateMappingList {
 			fromEdbMap[v.FromEdbInfoId] = v.EdbInfoId
-			if !utils.InArrayByInt(edbInfoIds, v.FromEdbInfoId) {
+			if !utils.InArrayByInt(fromEdbInfoIds, v.FromEdbInfoId) && (config.EdbInfoMode == 1 || req.EdbInfoType != v.FromEdbInfoType) {
 				deleteEdbInfoIds = append(deleteEdbInfoIds, v.EdbInfoId)
 			}
 		}
@@ -1364,11 +1389,10 @@ func (this *RangeChartChartInfoController) MultipleGraphConfigSaveEdb() {
 	// 普通指标批量新增\批量编辑
 	var saveReq data_manage.BatchEdbInfoCalculateBatchSaveReq
 	calculateEdbList := make([]data_manage.BatchEdbInfoCalculateBatchSaveSuccessResp, 0)
-	reqEdbList := make([]*data_manage.CalculateEdbInfoItem, 0)
+	addReqEdbList := make([]*data_manage.CalculateEdbInfoItem, 0)
+	editReqEdbList := make([]*data_manage.CalculateEdbInfoItem, 0)
 	for _, v := range req.EdbInfoList {
-		if edbInfoId, ok := fromEdbMap[v.EdbInfoId]; ok {
-			v.EdbInfoId = edbInfoId
-		}
+
 		v.CalculateId = strconv.Itoa(v.FromEdbInfoId)
 		v.EdbName = strings.Trim(v.EdbName, " ")
 		if v.EdbName == "" {
@@ -1418,43 +1442,73 @@ func (this *RangeChartChartInfoController) MultipleGraphConfigSaveEdb() {
 			continue
 		} else {
 		}
-		reqEdbList = append(reqEdbList, v)
+		if v.EdbInfoId > 0 {
+			editReqEdbList = append(editReqEdbList, v)
+		} else {
+			addReqEdbList = append(addReqEdbList, v)
+		}
 	}
-
-	if req.EdbInfoType == 0 { //普通指标
-		if len(reqEdbList) <= 0 {
-			br.Msg = "新增失败!"
-			if len(resp.Fail) > 0 {
-				br.ErrMsg = resp.Fail[0].Msg
-			} else {
-				br.Msg = "请选择指标"
-			}
-			return
+	if len(editReqEdbList) <= 0 && len(addReqEdbList) <= 0 {
+		br.Msg = "新增失败!"
+		if len(resp.Fail) > 0 {
+			br.ErrMsg = resp.Fail[0].Msg
+		} else {
+			br.Msg = "请选择指标"
 		}
+		return
+	}
+	if req.EdbInfoType == 0 { //普通指标
 		saveReq.Source = utils.DATA_SOURCE_CALCULATE_RANGEANLYSIS
 		saveReq.CalculateFormula = extraConfig
 		saveReq.AdminId = sysUser.AdminId
 		saveReq.AdminName = sysUser.RealName
-		saveReq.EdbList = reqEdbList
-		// 调用指标库去更新
-		reqJson, err := json.Marshal(saveReq)
-		if err != nil {
-			br.Msg = "参数解析异常!"
-			br.ErrMsg = "参数解析失败,Err:" + err.Error()
-			return
-		}
-		respItem, err := data.BatchSaveEdbCalculateMultiData(string(reqJson), this.Lang)
-		if err != nil {
-			br.Msg = "新增失败!"
-			br.ErrMsg = "新增失败,Err:" + err.Error()
-			return
+		if len(addReqEdbList) > 0 {
+			saveReq.EdbList = addReqEdbList
+			// 调用指标库去更新
+			reqJson, err := json.Marshal(saveReq)
+			if err != nil {
+				br.Msg = "参数解析异常!"
+				br.ErrMsg = "参数解析失败,Err:" + err.Error()
+				return
+			}
+			respItem, err := data.BatchSaveEdbCalculateMultiData(string(reqJson), this.Lang)
+			if err != nil {
+				br.Msg = "新增失败!"
+				br.ErrMsg = "新增失败,Err:" + err.Error()
+				return
+			}
+			if respItem.Ret != 200 {
+				br.Msg = respItem.Msg
+				br.ErrMsg = respItem.ErrMsg
+				return
+			}
+			resp = respItem.Data
+			calculateEdbList = respItem.Data.Success
 		}
-		if respItem.Ret != 200 {
-			br.Msg = respItem.Msg
-			br.ErrMsg = respItem.ErrMsg
-			return
+
+		if len(editReqEdbList) > 0 {
+			saveReq.EdbList = editReqEdbList
+			// 调用指标库去更新
+			reqJson, err := json.Marshal(saveReq)
+			if err != nil {
+				br.Msg = "参数解析异常!"
+				br.ErrMsg = "参数解析失败,Err:" + err.Error()
+				return
+			}
+			respItem, err := data.BatchEditEdbCalculateMultiData(string(reqJson), this.Lang)
+			if err != nil {
+				br.Msg = "更新失败!"
+				br.ErrMsg = "更新失败,Err:" + err.Error()
+				return
+			}
+			if respItem.Ret != 200 {
+				br.Msg = respItem.Msg
+				br.ErrMsg = respItem.ErrMsg
+				return
+			}
+			resp.Fail = append(resp.Fail, respItem.Data.Fail...)
+			calculateEdbList = append(calculateEdbList, respItem.Data.Success...)
 		}
-		calculateEdbList = respItem.Data.Success
 	} else if req.EdbInfoType == 1 {
 		// 预测指标
 		for _, v := range req.EdbInfoList {
@@ -1468,7 +1522,37 @@ func (this *RangeChartChartInfoController) MultipleGraphConfigSaveEdb() {
 			predictReq.FromEdbInfoId = v.FromEdbInfoId
 			predictReq.AdminId = sysUser.AdminId
 			predictReq.AdminName = sysUser.RealName
-			//todo 新增预测指标的区间计算指标
+			predictReq.Source = utils.DATA_SOURCE_PREDICT_CALCULATE_RANGEANLYSIS
+			reqJson, err := json.Marshal(predictReq)
+			if err != nil {
+				br.Msg = "参数解析异常!"
+				br.ErrMsg = "参数解析失败,Err:" + err.Error()
+				return
+			}
+			respItem, err := data.BatchSavePredictEdbData(string(reqJson), this.Lang)
+			if err != nil {
+				resp.Fail = append(resp.Fail, data_manage.BatchEdbInfoCalculateBatchSaveFailResp{
+					CalculateId: v.CalculateId,
+					Msg:         "新增失败!",
+					ErrMsg:      "新增失败,Err:" + err.Error(),
+				})
+				continue
+			}
+			if respItem.Ret != 200 {
+				resp.Fail = append(resp.Fail, data_manage.BatchEdbInfoCalculateBatchSaveFailResp{
+					CalculateId: v.CalculateId,
+					Msg:         respItem.Msg,
+					ErrMsg:      respItem.ErrMsg,
+				})
+				continue
+			}
+
+			calculateEdbList = append(calculateEdbList, data_manage.BatchEdbInfoCalculateBatchSaveSuccessResp{
+				CalculateId: v.CalculateId,
+				EdbInfoId:   respItem.Data.EdbInfoId,
+				UniqueCode:  respItem.Data.UniqueCode,
+				ClassifyId:  predictReq.ClassifyId,
+			})
 		}
 	}
 
@@ -1517,6 +1601,100 @@ func (this *RangeChartChartInfoController) MultipleGraphConfigSaveEdb() {
 			}
 		}
 	}
+	resp.Success = calculateEdbList
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "保存成功"
+	br.Data = resp
+	br.IsAddLog = true
+}
+
+// MultipleGraphConfigEdbList
+// @Title 获取指标列表接口
+// @Description 获取指标列表接口
+// @Param	request	body request.SaveMultipleGraphEdbReq true "type json string"
+// @Success Ret=200 返回指标id
+// @router /edb/list [get]
+func (this *RangeChartChartInfoController) MultipleGraphConfigEdbList() {
+	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
+	}
+
+	multipleGraphConfigId, _ := this.GetInt("MultipleGraphConfigId")
+	if multipleGraphConfigId <= 0 {
+		br.Msg = "参数错误"
+		br.ErrMsg = "参数错误,MultipleGraphConfigId Is Empty"
+		return
+	}
+
+	list := make([]*data_manage.ChartRangeAnalysisConfigEdbItem, 0)
+	resp := data_manage.ChartRangeAnalysisConfigEdbResp{EdbInfoList: list}
+
+	multipleGraphConfigEdbMappingList, err := data_manage.GetMultipleGraphConfigEdbMappingListByIdAndSource(multipleGraphConfigId, utils.CHART_SOURCE_RANGE_ANALYSIS)
+	if err != nil {
+		br.Msg = `保存失败`
+		br.ErrMsg = "查询配置与图表的关联关系失败,ERR:" + err.Error()
+		return
+	}
+	if len(multipleGraphConfigEdbMappingList) == 0 {
+		br.Ret = 200
+		br.Success = true
+		br.Msg = "操作成功"
+		br.Data = resp
+		br.IsAddLog = true
+		return
+	}
+
+	edbInfoIds := make([]int, 0)
+	for _, v := range multipleGraphConfigEdbMappingList {
+		edbInfoIds = append(edbInfoIds, v.EdbInfoId)
+	}
+	edbList, err := data_manage.GetChartEdbMappingListByEdbInfoIdList(edbInfoIds)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取图表,指标信息失败,Err:" + err.Error()
+		return
+	}
+	edbInfoMap := make(map[int]*data_manage.ChartEdbInfoMapping, 0)
+	for _, v := range edbList {
+		edbInfoMap[v.EdbInfoId] = v
+	}
+
+	edbCalculateMappingList, e := data_manage.GetEdbInfoCalculateMappingListByEdbInfoIds(edbInfoIds)
+	if e != nil {
+		br.Msg = `保存失败`
+		br.ErrMsg = "获取计算指标信息失败,ERR:" + e.Error()
+		return
+	}
+
+	// 说明指标还在,没有被删除
+	for _, v := range edbCalculateMappingList {
+		tmp := new(data_manage.ChartRangeAnalysisConfigEdbItem)
+		info, ok := edbInfoMap[v.EdbInfoId]
+		if ok {
+			tmp.EdbInfoId = v.EdbInfoId
+			tmp.Unit = info.Unit
+			tmp.UnitEn = info.UnitEn
+			tmp.Frequency = info.Frequency
+			tmp.EdbNameEn = info.EdbNameEn
+			tmp.EdbName = info.EdbName
+			tmp.ClassifyId = info.ClassifyId
+			tmp.FromEdbInfoId = v.FromEdbInfoId
+			tmp.EdbTypeInfo = info.EdbInfoCategoryType
+			list = append(list, tmp)
+		}
+	}
+	resp.EdbInfoList = list
 
 	br.Ret = 200
 	br.Success = true
@@ -1524,3 +1702,346 @@ func (this *RangeChartChartInfoController) MultipleGraphConfigSaveEdb() {
 	br.Data = resp
 	br.IsAddLog = true
 }
+
+// SearchByEs
+// @Title 图表模糊搜索(从es获取)
+// @Description  图表模糊搜索(从es获取)
+// @Param   Keyword   query   string  true       "图表名称"
+// @Param   IsShowMe   query   bool  true       "是否只看我的,true、false"
+// @Param   Source   query   int  true       "来源,3:相关性,4:滚动相关性,默认0:全部"
+// @Success 200 {object} data_manage.ChartInfo
+// @router /chart_info/search_by_es [get]
+func (this *RangeChartChartInfoController) SearchByEs() {
+	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 = paging.StartIndex(currentIndex, pageSize)
+
+	keyword := this.GetString("Keyword")
+
+	//只看我的
+	isShowMe, _ := this.GetBool("IsShowMe")
+	showSysId := 0
+	if isShowMe {
+		showSysId = sysUser.AdminId
+	}
+
+	sourceList := make([]int, 0)
+	sourceList = append(sourceList, utils.CHART_SOURCE_RANGE_ANALYSIS)
+
+	var searchList []*data_manage.ChartInfo
+	var total int64
+	var err error
+
+	// 获取当前账号的不可见指标
+	noPermissionChartIdList := make([]int, 0)
+	{
+		obj := data_manage.EdbInfoNoPermissionAdmin{}
+		confList, err := obj.GetAllChartListByAdminId(this.SysUser.AdminId)
+		if err != nil && err.Error() != utils.ErrNoRow() {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取不可见指标配置数据失败,Err:" + err.Error()
+			return
+		}
+		for _, v := range confList {
+			noPermissionChartIdList = append(noPermissionChartIdList, v.ChartInfoId)
+		}
+	}
+
+	if keyword != "" {
+		searchList, total, err = data.EsSearchChartInfo(keyword, showSysId, sourceList, noPermissionChartIdList, startSize, pageSize)
+	} else {
+		total, searchList, err = data_manage.ChartInfoSearchByEmptyKeyWord(showSysId, sourceList, noPermissionChartIdList, startSize, pageSize)
+		if err != nil && err.Error() != utils.ErrNoRow() {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取图表信息失败,Err:" + err.Error()
+			return
+		}
+	}
+
+	finalList := make([]*data_manage.ChartInfoMore, 0)
+	if len(searchList) > 0 {
+		chartInfoIds := ""
+		chartEdbMap := make(map[int][]*data_manage.ChartEdbInfoMapping)
+		for _, v := range searchList {
+			chartInfoIds += strconv.Itoa(v.ChartInfoId) + ","
+		}
+		if chartInfoIds != "" {
+			chartInfoIds = strings.Trim(chartInfoIds, ",")
+			//判断是否需要展示英文标识
+			edbList, e := data_manage.GetChartEdbMappingListByChartInfoIds(chartInfoIds)
+			if e != nil {
+				br.Msg = "获取失败"
+				br.ErrMsg = "获取图表,指标信息失败,Err:" + e.Error()
+				return
+			}
+			for _, v := range edbList {
+				chartEdbMap[v.ChartInfoId] = append(chartEdbMap[v.ChartInfoId], v)
+			}
+		}
+
+		for _, v := range searchList {
+			tmp := new(data_manage.ChartInfoMore)
+			tmp.ChartInfo = *v
+			// 图表数据权限
+			tmp.HaveOperaAuth = true
+			//判断是否需要展示英文标识
+			if edbTmpList, ok := chartEdbMap[v.ChartInfoId]; ok {
+				tmp.IsEnChart = data.CheckIsEnChart(v.ChartNameEn, edbTmpList, v.Source, v.ChartType)
+			}
+			finalList = append(finalList, tmp)
+		}
+	}
+	//新增搜索词记录
+	{
+		searchKeyword := new(data_manage.SearchKeyword)
+		searchKeyword.KeyWord = keyword
+		searchKeyword.CreateTime = time.Now()
+		go data_manage.AddSearchKeyword(searchKeyword)
+	}
+
+	page := paging.GetPaging(currentIndex, pageSize, int(total))
+	resp := data_manage.ChartInfoListByEsResp{
+		Paging: page,
+		List:   finalList,
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+// BaseInfoEdit
+// @Title 编辑图表基础信息接口
+// @Description 编辑图表基础信息接口
+// @Param	request	body data_manage.EditChartInfoBaseReq true "type json string"
+// @Success Ret=200 编辑成功
+// @router /chart_info/base/edit [post]
+func (this *RangeChartChartInfoController) BaseInfoEdit() {
+	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
+	}
+	var req data_manage.EditChartRangeBaseReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	req.ChartName = strings.Trim(req.ChartName, " ")
+	if req.ChartInfoId <= 0 {
+		br.Msg = "请选择图表"
+		return
+	}
+	if req.ChartName == "" {
+		br.Msg = "请输入图表名称"
+		return
+	}
+
+	chartItem, e := data_manage.GetChartInfoById(req.ChartInfoId)
+	if e != nil {
+		if e.Error() == utils.ErrNoRow() {
+			br.Msg = "图表已被删除, 请刷新页面"
+			return
+		}
+		br.Msg = "获取图表信息失败"
+		br.ErrMsg = "获取图表信息失败, Err: " + e.Error()
+		return
+	}
+	if chartItem.Source != utils.CHART_SOURCE_RANGE_ANALYSIS {
+		br.Msg = "该图不是区间计算图表"
+		return
+	}
+
+	var condition string
+	var pars []interface{}
+
+	condition += " AND chart_info_id <> ? AND source = ? "
+	pars = append(pars, req.ChartInfoId, utils.CHART_SOURCE_RANGE_ANALYSIS)
+
+	switch this.Lang {
+	case utils.EnLangVersion:
+		condition += " AND chart_name_en = ? "
+	default:
+		condition += " AND chart_name = ? "
+	}
+	pars = append(pars, req.ChartName)
+	existItem, err := data_manage.GetChartInfoByCondition(condition, pars)
+	if err != nil {
+		if err.Error() != utils.ErrNoRow() {
+			br.Msg = "判断英文图表名称是否存在失败"
+			br.ErrMsg = "判断英文图表名称是否存在失败,Err:" + err.Error()
+			return
+		}
+	}
+	if err == nil && existItem.ChartInfoId > 0 {
+		br.Msg = existItem.ChartName + ":" + req.ChartName + "图表名称已存在"
+		return
+	}
+
+	switch this.Lang {
+	case utils.EnLangVersion:
+		chartItem.ChartNameEn = req.ChartName
+	default:
+		chartItem.ChartName = req.ChartName
+	}
+
+	chartItem.ModifyTime = time.Now().Local()
+	if e := chartItem.Update([]string{"ChartName", "ChartNameEn", "ModifyTime"}); e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "更新图表信息失败, Err: " + e.Error()
+		return
+	}
+
+	//添加es数据
+	go data.EsAddOrEditChartInfo(chartItem.ChartInfoId)
+	//修改my eta es数据
+	go data.EsAddOrEditMyChartInfoByChartInfoId(chartItem.ChartInfoId)
+
+	//新增操作日志
+	{
+		chartLog := new(data_manage.ChartInfoLog)
+		chartLog.ChartName = chartItem.ChartName
+		chartLog.ChartInfoId = req.ChartInfoId
+		chartLog.ChartClassifyId = chartItem.ChartClassifyId
+		chartLog.SysUserId = sysUser.AdminId
+		chartLog.SysUserRealName = sysUser.RealName
+		chartLog.UniqueCode = chartItem.UniqueCode
+		chartLog.CreateTime = time.Now()
+		chartLog.Content = string(this.Ctx.Input.RequestBody)
+		chartLog.Status = "编辑区间计算图表基础信息"
+		chartLog.Method = this.Ctx.Input.URL()
+		go data_manage.AddChartInfoLog(chartLog)
+	}
+
+	// 清除缓存
+	if utils.Re == nil && utils.Rc != nil {
+		_ = utils.Rc.Delete(utils.HZ_CHART_LIB_DETAIL + chartItem.UniqueCode) //图表分享链接缓存
+		_ = utils.Rc.Delete(data.GetChartInfoDataKey(req.ChartInfoId))
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "编辑成功"
+	br.IsAddLog = true
+}
+
+// @Title 保存图表接口
+// @Description 保存图表接口
+// @Param	request	body data_manage.SaveChartInfoReq true "type json string"
+// @Success Ret=200 返回图表id
+// @router /chart_info/save [post]
+func (this *RangeChartChartInfoController) ChartInfoSave() {
+	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
+	}
+
+	var req data_manage.SaveChartRangeReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	if req.ChartInfoId <= 0 {
+		br.Msg = "参数错误!"
+		return
+	}
+
+	chartItem, err := data_manage.GetChartInfoById(req.ChartInfoId)
+	if err != nil {
+		if err.Error() == utils.ErrNoRow() {
+			br.Msg = "图表已被删除,请刷新页面!"
+			br.ErrMsg = "图表已被删除,请刷新页面,ChartInfoId:" + strconv.Itoa(req.ChartInfoId)
+			return
+		}
+		br.Msg = "获取图表信息失败!"
+		br.ErrMsg = "获取图表信息失败,Err:" + err.Error()
+		return
+	}
+
+	//图表操作权限
+	//ok := data.CheckOpChartPermission(sysUser, chartItem.SysUserId)
+	//if !ok {
+	//	br.Msg = "没有该图表的操作权限"
+	//	br.ErrMsg = "没有该图表的操作权限"
+	//	return
+	//}
+
+	err = data_manage.EditRangeChartInfo(&req)
+	if err != nil {
+		br.Msg = "保存失败"
+		br.ErrMsg = "保存失败,Err:" + err.Error()
+		return
+	}
+
+	key := utils.HZ_CHART_LIB_DETAIL + chartItem.UniqueCode
+	if utils.Re == nil && utils.Rc != nil {
+		utils.Rc.Delete(key)
+	}
+
+	//修改es数据
+	go data.EsAddOrEditChartInfo(chartItem.ChartInfoId)
+	//修改my eta es数据
+	go data.EsAddOrEditMyChartInfoByChartInfoId(chartItem.ChartInfoId)
+
+	//新增操作日志
+	{
+		chartLog := new(data_manage.ChartInfoLog)
+		chartLog.ChartName = chartItem.ChartName
+		chartLog.ChartInfoId = req.ChartInfoId
+		chartLog.ChartClassifyId = chartItem.ChartClassifyId
+		chartLog.SysUserId = sysUser.AdminId
+		chartLog.SysUserRealName = sysUser.RealName
+		chartLog.UniqueCode = chartItem.UniqueCode
+		chartLog.CreateTime = time.Now()
+		chartLog.Content = string(this.Ctx.Input.RequestBody)
+		chartLog.Status = "修改配置项"
+		chartLog.Method = this.Ctx.Input.URI()
+		go data_manage.AddChartInfoLog(chartLog)
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "保存成功"
+	br.IsAddLog = true
+}

+ 60 - 29
controllers/data_manage/sci_hq_data.go

@@ -93,13 +93,17 @@ func (this *SciHqDataController) AddClassify() {
 		br.Msg = "操作异常"
 		return
 	}
-	ok, err := data.AddSciHqClassify(req.ClassifyName, this.Lang, req.ParentId)
+	ok, msg, err := data.AddSciHqClassify(req.ClassifyName, this.Lang, req.ParentId)
 	if err != nil {
 		br.Msg = "添加失败"
 		br.ErrMsg = "添加失败,Err:" + err.Error()
 		return
 	}
 	if !ok {
+		if msg != "" {
+			br.Msg = msg
+			return
+		}
 		br.Msg = "添加失败"
 		return
 	}
@@ -338,7 +342,27 @@ func (this *SciHqDataController) BatchIndexList() {
 			pars = append(pars, req.SelectedId)
 		}
 	}
-	if req.ClassifyId >= 0 {
+	if req.ClassifyId < 0 {
+		br.Msg = "分类选择错误"
+		return
+	}
+	if req.ClassifyId > 0 {
+		childClassify, err := data_manage.GetChildSciHqClassifyListById(req.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, req.ClassifyId)
+		}
+	} else {
 		condition += ` AND classify_id=?`
 		pars = append(pars, req.ClassifyId)
 	}
@@ -455,7 +479,7 @@ func (this *SciHqDataController) IndexPageList() {
 // SearchList
 // @Title 卓创红期模糊搜索
 // @Description 卓创红期模糊搜索
-// @Param   Keyword   query   string  ture       "关键字搜索"
+// @Param   Keyword   query   string  true       "关键字搜索"
 // @Success 200 {object} models.BaseResponse
 // @router /sci_hq/search_list [get]
 func (this *SciHqDataController) SearchList() {
@@ -509,6 +533,16 @@ func (this *SciHqDataController) SingleData() {
 		br.ErrMsg = "获取指标信息失败,Err:" + err.Error()
 		return
 	}
+	edbInfo, err := data_manage.GetEdbInfoByEdbCode(utils.DATA_SOURCE_SCI_HQ, indexInfo.IndexCode)
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		br.Msg = "获取指标数据失败"
+		br.ErrMsg = "获取指标库数据失败,Err:" + err.Error()
+		return
+	}
+	var edbInfoId int
+	if edbInfo != nil {
+		edbInfoId = edbInfo.EdbInfoId
+	}
 	dataList, err := data_manage.GetSciHqDataByIndexId(baseFromSciHqIndexId)
 	if err != nil {
 		br.Msg = "获取数据失败"
@@ -519,6 +553,7 @@ func (this *SciHqDataController) SingleData() {
 	ret.ClassifyId = indexInfo.ClassifyId
 	ret.BaseFromSciHqIndexId = indexInfo.BaseFromSciHqIndexId
 	ret.IndexCode = indexInfo.IndexCode
+	ret.EdbInfoId = edbInfoId
 	ret.IndexName = indexInfo.IndexName
 	ret.Frequency = indexInfo.Frequency
 	ret.CreateTime = indexInfo.CreateTime.Format(utils.FormatDateTime)
@@ -1344,9 +1379,9 @@ func (this *SciHqDataController) DeleteSciHqData() {
 // ExportSciHqList
 // @Title 导出Sci数据
 // @Description 导出Sci数据
-// @Param   request	body request.ExportSciHqExcelReq true "type json string"
+// @Param   ClassifyId   query   int  true       "关键字搜索"
 // @Success 200  导出成功
-// @router /export/sciHqList [post]
+// @router /export/sciHqList [get]
 func (this *SciHqDataController) ExportSciHqList() {
 	br := new(models.BaseResponse).Init()
 	defer func() {
@@ -1360,42 +1395,38 @@ func (this *SciHqDataController) ExportSciHqList() {
 		return
 	}
 
-	//typeName := this.GetString("TypeName") //分类
-	//frequency := this.GetString("Frequency")
-	var req request.ExportSciHqExcelReq
-	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
-		br.Msg = "参数解析异常!"
-		br.ErrMsg = "参数解析失败,Err:" + e.Error()
+	classifyId, _ := this.GetInt("ClassifyId")
+	if classifyId < 0 {
+		br.Msg = "请选择分类"
 		return
 	}
 	secNameList := make([]*models.EdbdataExportList, 0)
-
 	dir, _ := os.Executable()
 	exPath := filepath.Dir(dir)
-
 	downLoadnFilePath := exPath + "/" + time.Now().Format(utils.FormatDateTimeUnSpace) + ".xlsx"
 	xlsxFile := xlsx.NewFile()
 
 	var condition string
 	var pars []interface{}
-	if req.KeyWord != "" {
-		condition += `AND (index_code=? OR index_name=?)`
-		pars = utils.GetLikeKeywordPars(pars, req.KeyWord, 2)
-	}
-	if req.IsSelectedAll {
-		if len(req.IndexCode) > 0 {
-			condition += ` AND index_code NOT IN (` + utils.GetOrmInReplace(len(req.IndexCode)) + `)`
-			pars = append(pars, req.IndexCode)
+	if classifyId > 0 {
+		childClassify, err := data_manage.GetChildSciHqClassifyListById(classifyId)
+		if err != nil {
+			br.Msg = "下载失败"
+			br.ErrMsg = "获取分类失败,Err:" + err.Error()
+			return
 		}
-	} else {
-		if len(req.IndexCode) > 0 {
-			condition += ` AND index_code IN (` + utils.GetOrmInReplace(len(req.IndexCode)) + `)`
-			pars = append(pars, req.IndexCode)
+		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 req.ClassifyId >= 0 {
+	} else {
 		condition += ` AND classify_id=?`
-		pars = append(pars, req.ClassifyId)
+		pars = append(pars, classifyId)
 	}
 	frequencies, err := data_manage.GetSciHqFrequencyByCondition(condition, pars)
 	if err != nil {
@@ -1430,7 +1461,7 @@ func (this *SciHqDataController) ExportSciHqList() {
 		unitRow := sheetNew.AddRow()
 		lastModifyDateRow := sheetNew.AddRow()
 		//获取分类下指标最大数据量
-		dataMax, err := data_manage.GetSciHqDataMaxCount(req.ClassifyId)
+		dataMax, err := data_manage.GetSciHqDataMaxCount(condition, pars)
 		if err != nil {
 			fmt.Println("获取指标最大数据量失败", err.Error())
 			return

+ 83 - 43
controllers/target.go

@@ -971,7 +971,7 @@ func (this *TargetController) ExportDataList() {
 
 	var condition string
 	var pars []interface{}
-	//分类ID
+	// 指标名称
 	if keyWord != "" {
 		condition += ` AND  a.SEC_NAME LIKE '%` + keyWord + `%'`
 	}
@@ -993,10 +993,45 @@ func (this *TargetController) ExportDataList() {
 	//	condition += ` AND a.frequency = ? `
 	//	pars = append(pars, frequency)
 	//}
+	permissionUserId := sysUser.AdminId
+	if sysUser.RoleTypeCode == utils.ROLE_TYPE_CODE_ADMIN {
+		permissionUserId = 0
+	}
+
+	childClassifyIdList := make([]int, 0)
+	// 所属分类
 	if classifyId > 0 {
-		condition += ` AND a.classify_id = ? `
-		pars = append(pars, classifyId)
+		// 获取有用权限的分类
+		classifyList, err := models.GetEdbdataClassify(int64(permissionUserId))
+		if err != nil {
+			return
+		}
+
+		var isParent bool
+		for _, v := range classifyList {
+			if v.ClassifyId == classifyId {
+				isParent = true
+				childClassifyIdList = append(childClassifyIdList, v.ClassifyId)
+				if v.Child != nil && len(v.Child) > 0 {
+					for _, vv := range v.Child {
+						childClassifyIdList = append(childClassifyIdList, vv.ClassifyId)
+					}
+				}
+				break
+			}
+		}
+
+		// 如果是最小级,那么就把自己放进去
+		if !isParent {
+			childClassifyIdList = append(childClassifyIdList, classifyId)
+		}
 	}
+
+	// 如果所选分类是一级时,那么是一级下的所有分类;如果是二级时,那么是二级自己本身
+	num := len(childClassifyIdList)
+	condition += ` AND a.classify_id in (` + utils.GetOrmInReplace(num) + `) `
+	pars = append(pars, childClassifyIdList)
+
 	if mobile != "" {
 		condition += ` AND d.mobile=? `
 		pars = append(pars, mobile)
@@ -1017,28 +1052,39 @@ func (this *TargetController) ExportDataList() {
 	dir, _ := os.Executable()
 	exPath := filepath.Dir(dir)
 
-	downLoadnFilePath := exPath + "/" + time.Now().Format(utils.FormatDateTimeUnSpace) + ".xlsx"
+	downloadFilePath := exPath + "/" + time.Now().Format(utils.FormatDateTimeUnSpace) + ".xlsx"
 	xlsxFile := xlsx.NewFile()
 	if err != nil {
 		br.Msg = "生成文件失败"
 		br.ErrMsg = "生成文件失败"
 		return
 	}
-	var frequencies []*string
-	if keyWord == "" {
-		frequencies, err = models.GetEdbDataFrequency(classifyId)
+	var frequencies []string
+	if len(childClassifyIdList) > 0 {
+		frequencies, err = models.GetEdbDataFrequencyByClassifyIdList(childClassifyIdList)
 		if err != nil {
 			br.Msg = "查询频度失败"
 			br.ErrMsg = "查询频度失败"
 			return
 		}
-	} else {
+	} else if tradeCode != `` {
+		manualEdb, err := models.GetEdbinfoByTradeCode(tradeCode)
+		if err != nil {
+			br.Msg = "查询指标信息失败"
+			br.ErrMsg = "查询指标信息失败,err:" + err.Error()
+			return
+		}
+		frequencies = append(frequencies, manualEdb.Frequency)
+	} else if keyWord != `` {
 		frequencies, err = models.GetEdbDataFrequencyByKeyord(keyWord)
 		if err != nil {
 			br.Msg = "查询频度失败"
 			br.ErrMsg = "查询频度失败"
 			return
 		}
+	} else {
+		// 啥也没选的情况下
+		frequencies = append(frequencies, `日度`, `周度`, `月度`, `季度`, `半年度`, `年度`)
 	}
 
 	fileName := `手工数据`
@@ -1070,7 +1116,7 @@ func (this *TargetController) ExportDataList() {
 		}
 		var sheet *xlsx.Sheet
 		if len(secNameList) > 0 {
-			sheet, err = xlsxFile.AddSheet(*frequency)
+			sheet, err = xlsxFile.AddSheet(frequency)
 			if err != nil {
 				br.Msg = "新增Sheet失败"
 				br.ErrMsg = "新增Sheet失败,Err:" + err.Error()
@@ -1147,7 +1193,7 @@ func (this *TargetController) ExportDataList() {
 
 	}
 
-	err = xlsxFile.Save(downLoadnFilePath)
+	err = xlsxFile.Save(downloadFilePath)
 	if err != nil {
 		//有指标无数据时先导出一遍空表
 		sheet, err := xlsxFile.AddSheet("无数据")
@@ -1159,19 +1205,20 @@ func (this *TargetController) ExportDataList() {
 		rowSecName := sheet.AddRow()
 		celSecName := rowSecName.AddCell()
 		celSecName.SetValue("")
-		err = xlsxFile.Save(downLoadnFilePath)
+		err = xlsxFile.Save(downloadFilePath)
 		if err != nil {
 			br.Msg = "保存文件失败"
 			br.ErrMsg = "保存文件失败"
 			return
 		}
 	}
-
-	fileName += time.Now().Format("06.01.02") + `.xlsx` //文件名称
-	this.Ctx.Output.Download(downLoadnFilePath, fileName)
 	defer func() {
-		os.Remove(downLoadnFilePath)
+		os.Remove(downloadFilePath)
 	}()
+
+	fileName += time.Now().Format("06.01.02") + `.xlsx` //文件名称
+	this.Ctx.Output.Download(downloadFilePath, fileName)
+
 	br.Ret = 200
 	br.Success = true
 	br.Msg = "success"
@@ -3329,22 +3376,8 @@ func (this *TargetController) ExcelDataAdd() {
 	userId := sysUser.AdminId
 	if sysUser.RoleTypeCode == utils.ROLE_TYPE_CODE_ADMIN {
 		userId = 0
-
-		// 校验下当前用户是否有该指标的权限
-		count, err := models.GetCountManualUserClassify(sysUser.AdminId, req.ClassifyId)
-		if err != nil {
-			br.Msg = "获取分类数据失败"
-			br.ErrMsg = "获取分类数据失败,err:" + err.Error()
-			return
-		}
-
-		if count <= 0 {
-			br.Msg = "无权访问"
-			br.ErrMsg = "无权访问"
-			br.IsSendEmail = false
-			return
-		}
 	}
+
 	//获取账户所拥有权限的分类id集合
 	classifyIdList, err := data.GetUserManualClassifyIdList(userId)
 	if err != nil {
@@ -3352,6 +3385,12 @@ func (this *TargetController) ExcelDataAdd() {
 		br.Msg = "获取拥有的分类数据失败,Err:" + err.Error()
 		return
 	}
+	if !utils.InArrayByInt(classifyIdList, req.ClassifyId) {
+		br.Msg = "无权访问"
+		br.ErrMsg = "无权访问"
+		br.IsSendEmail = false
+		return
+	}
 
 	//操作指标,新增指标及数据等
 	{
@@ -3440,6 +3479,20 @@ func (this *TargetController) ExcelDataAdd() {
 						continue
 					}
 
+					// 指标信息变更,需要更新
+					if frequency != target.Frequency || unit != target.Unit || req.ClassifyId != target.ClassifyId {
+						fmt.Println("更新指标频度或单位")
+						err = models.ModifyEdbinfo(target.TradeCode, unit, frequency, req.ClassifyId)
+						if err != nil {
+							fmt.Println("EditEdbinfo err:", err.Error())
+							return
+						}
+						// 指标信息变更
+						if _, isAdd := addEdbTradeMap[target.TradeCode]; !isAdd {
+							updateEdbTradeMap[target.TradeCode] = true
+						}
+					}
+
 					//判断指标数据是否已经存在
 					tmpDataMap, ok2 := edbCodeDataMap[target.TradeCode]
 					if !ok2 {
@@ -3495,19 +3548,6 @@ func (this *TargetController) ExcelDataAdd() {
 							// 指标数据变更
 							updateDataTradeMap[target.TradeCode] = true
 						}
-
-						if frequency != target.Frequency || unit != target.Unit || req.ClassifyId != target.ClassifyId {
-							fmt.Println("更新指标频度或单位")
-							err = models.ModifyEdbinfo(target.TradeCode, unit, frequency, req.ClassifyId)
-							if err != nil {
-								fmt.Println("EditEdbinfo err:", err.Error())
-								return
-							}
-							// 指标信息变更
-							if _, isAdd := addEdbTradeMap[target.TradeCode]; !isAdd {
-								updateEdbTradeMap[target.TradeCode] = true
-							}
-						}
 					} else { //数据不存在,进行新增操作
 						if target.TradeCode != "" && createDate != "" && closeVal != "" {
 							fmt.Println("新增")

+ 1 - 0
models/data_manage/base_from_eia_stero.go

@@ -112,6 +112,7 @@ type EiaSteoIndexListResp struct {
 	BaseFromEiaSteoClassifyId int                `description:"指标分类id"`
 	IndexCode                 string             `description:"指标编码"`
 	IndexName                 string             `description:"指标名称(中文名称)"`
+	EdbInfoId                 int                `description:"指标库id"`
 	Unit                      string             `description:"单位"`
 	Frequency                 string             `description:"频度"`
 	StartDate                 string             `description:"开始日期"`

+ 48 - 0
models/data_manage/base_from_ly_classify.go

@@ -0,0 +1,48 @@
+// Package data_manage
+// @Author gmy 2024/8/7 9:26:00
+package data_manage
+
+import "github.com/beego/beego/v2/client/orm"
+
+type BaseFromLyClassify struct {
+	BaseFromLyClassifyId int    `orm:"column(base_from_ly_classify_id);pk" description:"分类ID"`
+	CreateTime           string `orm:"column(create_time)" description:"创建时间"`
+	ModifyTime           string `orm:"column(modify_time)" description:"修改时间"`
+	ClassifyName         string `orm:"column(classify_name)" description:"分类名称"`
+	ParentId             int    `orm:"column(parent_id)" description:"上级id"`
+	Sort                 int    `orm:"column(sort)" description:"排序字段,越小越靠前"`
+	ClassifyNameEn       string `orm:"column(classify_name_en)" description:"英文分类名称"`
+}
+
+type BaseFromLyClassifyAndIndexInfo struct {
+	BaseFromLyClassifyId int    `orm:"column(base_from_ly_classify_id);pk" description:"分类ID"`
+	CreateTime           string `orm:"column(create_time)" description:"创建时间"`
+	ModifyTime           string `orm:"column(modify_time)" description:"修改时间"`
+	ClassifyName         string `orm:"column(classify_name)" description:"分类名称"`
+	ParentId             int    `orm:"column(parent_id)" description:"上级id"`
+	Sort                 int    `orm:"column(sort)" description:"排序字段,越小越靠前"`
+	ClassifyNameEn       string `orm:"column(classify_name_en)" description:"英文分类名称"`
+	IndexId              int    `orm:"column(base_from_ly_index_id)" description:"指标id"`
+	IndexCode            string `orm:"column(index_code)" description:"指标编码"`
+	IndexName            string `orm:"column(index_name)" description:"指标名称"`
+}
+
+func init() {
+	orm.RegisterModel(new(BaseFromLyClassify))
+}
+
+// GetAllLyClassify 查询所有分类
+func GetAllLyClassify() (items []*BaseFromLyClassify, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT * FROM base_from_ly_classify ORDER BY sort asc`
+	_, err = o.Raw(sql).QueryRows(&items)
+	return
+}
+
+// GetLyClassifyById 根据分类id查询
+func GetLyClassifyById(classifyId int) (item *BaseFromLyClassify, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT * FROM base_from_ly_classify WHERE base_from_ly_classify_id=?`
+	err = o.Raw(sql, classifyId).QueryRow(&item)
+	return
+}

+ 87 - 0
models/data_manage/base_from_ly_data.go

@@ -0,0 +1,87 @@
+// Package data_manage
+// @Author gmy 2024/8/7 9:50:00
+package data_manage
+
+import (
+	"github.com/beego/beego/v2/client/orm"
+	"github.com/rdlucklib/rdluck_tools/paging"
+	"strings"
+)
+
+type BaseFromLyData struct {
+	BaseFromLyDataId  int     `orm:"column(base_from_ly_data_id);pk" description:"数据ID"`
+	CreateTime        string  `orm:"column(create_time)" description:"创建时间"`
+	ModifyTime        string  `orm:"column(modify_time)" description:"修改时间"`
+	BaseFromLyIndexId int     `orm:"column(base_from_ly_index_id)" description:"指标id"`
+	IndexCode         string  `orm:"column(index_code)" description:"指标编码"`
+	DataTime          string  `orm:"column(data_time)" description:"数据日期"`
+	Value             float64 `orm:"column(value)" description:"数据值"`
+}
+
+func init() {
+	orm.RegisterModel(new(BaseFromLyData))
+}
+
+type BaseFromLyDataPage struct {
+	List   []*BaseFromLyData  `description:"指标数据列表"`
+	Paging *paging.PagingItem `description:"分页数据"`
+}
+
+// GetLyDataCountByIndexId 获取指标数据总数
+func GetLyDataCountByIndexId(indexId int) (count int, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT count(*) FROM base_from_ly_data WHERE base_from_ly_index_id=?`
+	err = o.Raw(sql, indexId).QueryRow(&count)
+	return
+}
+
+// GetLyDataPageByIndexId 获取指标数据分页列表
+func GetLyDataPageByIndexId(indexId int, startSize, pageSize int) (items []*BaseFromLyData, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT * FROM base_from_ly_data WHERE base_from_ly_index_id=? ORDER BY data_time desc LIMIT ?,?`
+	_, err = o.Raw(sql, indexId, startSize, pageSize).QueryRows(&items)
+	return
+}
+
+// GetBaseFromLyDataByIndexCode 根据指标编码查询
+func GetBaseFromLyDataByIndexCode(indexCode string) (items []*BaseFromLyData, err error) {
+	sql := `SELECT * FROM base_from_ly_data WHERE index_code=? ORDER BY data_time desc`
+	o := orm.NewOrmUsingDB("data")
+	_, err = o.Raw(sql, indexCode).QueryRows(&items)
+	return
+}
+
+func GetLyDataListByIndexCodes(IndexCodes string) (items []string, err error) {
+	sql := ` SELECT data_time FROM base_from_ly_data WHERE index_code IN(` + IndexCodes + `)  GROUP BY data_time DESC `
+	o := orm.NewOrmUsingDB("data")
+	_, err = o.Raw(sql).QueryRows(&items)
+	return
+}
+
+// GetLyDataLastByIndexCode 根据指标编码查询 返回ModifyTime最后一条数据
+func GetLyDataLastByIndexCode(indexCodes []string) (items []*BaseFromLyData, err error) {
+	o := orm.NewOrmUsingDB("data")
+
+	// 将 indexCodes 切片转换为逗号分隔的字符串
+	placeholders := strings.Repeat("?,", len(indexCodes)-1) + "?"
+
+	// 构造 SQL 查询
+	sql := `
+        SELECT t1.*
+        FROM base_from_ly_data t1
+        INNER JOIN (
+            SELECT index_code, MAX(modify_time) AS max_modify_time
+            FROM base_from_ly_data
+            WHERE index_code IN (` + placeholders + `)
+            GROUP BY index_code
+        ) t2 
+        ON t1.index_code = t2.index_code AND t1.modify_time = t2.max_modify_time
+    `
+
+	// 执行 SQL 查询
+	_, err = o.Raw(sql, indexCodes).QueryRows(&items)
+	if err != nil {
+		return nil, err
+	}
+	return items, nil
+}

+ 244 - 0
models/data_manage/base_from_ly_index.go

@@ -0,0 +1,244 @@
+// Package data_manage
+// @Author gmy 2024/8/7 9:38:00
+package data_manage
+
+import (
+	"github.com/beego/beego/v2/client/orm"
+	"github.com/rdlucklib/rdluck_tools/paging"
+)
+
+type BaseFromLyIndex struct {
+	BaseFromLyIndexId    int    `orm:"column(base_from_ly_index_id);pk" description:"指标ID"`
+	CreateTime           string `orm:"column(create_time)" description:"创建时间"`
+	ModifyTime           string `orm:"column(modify_time)" description:"修改时间"`
+	BaseFromLyClassifyId int    `orm:"column(base_from_ly_classify_id)" description:"原始数据指标分类id"`
+	IndexCode            string `orm:"column(index_code)" description:"指标编码"`
+	IndexName            string `orm:"column(index_name)" description:"指标名称"`
+	Frequency            string `orm:"column(frequency)" description:"频度"`
+	Unit                 string `orm:"column(unit)" description:"单位"`
+	EdbExist             int    `orm:"column(edb_exist)" description:"指标库是否已添加:0-否;1-是"`
+}
+
+// 在 init 函数中注册模型
+func init() {
+	orm.RegisterModel(new(BaseFromLyIndex))
+}
+
+type BaseFromLyIndexPage struct {
+	List   []*BaseFromLyIndexAndData `description:"指标列表"`
+	Paging *paging.PagingItem        `description:"分页数据"`
+}
+
+type BaseFromLyIndexBatchAddCheckReq struct {
+	IndexCodes []string `form:"IndexCodes" description:"指标编码列表"`
+}
+
+type BaseFromLyIndexNameCheck struct {
+	IndexCode string `from:"IndexCode" description:"指标编码"`
+	IndexName string `from:"IndexName" description:"指标名称"`
+}
+
+type NameCheckResult struct {
+	IndexCode string `from:"EdbCode" description:"edb编码"`
+	IndexName string `from:"EdbName" description:"edb名称"`
+	Exist     bool
+}
+
+type BaseFromLyIndexAndData struct {
+	BaseFromLyIndexId    int     `orm:"column(base_from_ly_index_id);pk" description:"指标ID"`
+	CreateTime           string  `orm:"column(create_time)" description:"创建时间"`
+	ModifyTime           string  `orm:"column(modify_time)" description:"修改时间"`
+	BaseFromLyClassifyId int     `orm:"column(base_from_ly_classify_id)" description:"原始数据指标分类id"`
+	IndexCode            string  `orm:"column(index_code)" description:"指标编码"`
+	IndexName            string  `orm:"column(index_name)" description:"指标名称"`
+	Frequency            string  `orm:"column(frequency)" description:"频度"`
+	Unit                 string  `orm:"column(unit)" description:"单位"`
+	EdbExist             int     `orm:"column(edb_exist)" description:"指标库是否已添加:0-否;1-是"`
+	ModifyTimeMax        string  `json:"modify_time_max" description:"最后修改时间"`
+	Value                float64 `orm:"column(value)" description:"数据值"`
+}
+
+type IndexCheckData struct {
+	IndexCode  string `orm:"column(index_code)" description:"指标编码"`
+	IndexName  string `orm:"column(index_name)" description:"指标名称"`
+	Frequency  string `orm:"column(frequency)" description:"频度"`
+	Unit       string `orm:"column(unit)" description:"单位"`
+	EdbInfoId  int    `json:"edb_info_id" description:"指标库主键id"`
+	UniqueCode string `json:"unique_code" description:"指标库唯一编码"`
+	ClassifyId int    `json:"classify_id" description:"分类id"`
+}
+
+// GetLyIndexByClassifyIds 通过分类ids查询指标列表
+func GetLyIndexByClassifyIds(classifyIds []int) (items []*BaseFromLyIndex, err error) {
+	o := orm.NewOrmUsingDB("data")
+
+	// 创建查询条件
+	qs := o.QueryTable("base_from_ly_index")
+
+	// 使用 Filter 进行查询
+	_, err = qs.Filter("base_from_ly_classify_id__in", classifyIds).All(&items)
+
+	return
+}
+
+// GetLyIndexCount 获取指标总数
+func GetLyIndexCount(classifyId string, searchParam string) (count int, err error) {
+	o := orm.NewOrmUsingDB("data")
+
+	// 构建 SQL 查询语句
+	sql := `SELECT COUNT(*) FROM base_from_ly_index WHERE 1=1`
+
+	var params []interface{}
+
+	// 添加 classifyId 过滤条件
+	if classifyId != "" {
+		sql += ` AND base_from_ly_classify_id = ?`
+		params = append(params, classifyId)
+	}
+
+	// 添加搜索条件
+	if searchParam != "" {
+		sql += ` AND (index_name LIKE ? OR index_code = ?)`
+		params = append(params, "%"+searchParam+"%", searchParam)
+	}
+
+	// 执行查询
+	err = o.Raw(sql, params...).QueryRow(&count)
+	if err != nil {
+		return 0, err
+	}
+	return count, nil
+}
+
+// GetLyIndexPage 获取指标列表
+func GetLyIndexPage(classifyId string, searchParam string, currentIndex, pageSize int) (items []*BaseFromLyIndexAndData, err error) {
+	o := orm.NewOrmUsingDB("data")
+
+	// 构建 SQL 查询语句
+	sql := `SELECT * FROM base_from_ly_index WHERE 1=1`
+
+	var params []interface{}
+
+	// 添加 classifyId 过滤条件
+	if classifyId != "" {
+		sql += ` AND base_from_ly_classify_id = ?`
+		params = append(params, classifyId)
+	}
+
+	// 添加搜索条件
+	if searchParam != "" {
+		sql += ` AND (index_name LIKE ? OR index_code = ?)`
+		params = append(params, "%"+searchParam+"%", searchParam)
+	}
+
+	// 添加排序和分页条件
+	sql += ` ORDER BY base_from_ly_index_id DESC LIMIT ?, ?`
+	params = append(params, (currentIndex-1)*pageSize, pageSize)
+
+	// 执行查询
+	_, err = o.Raw(sql, params...).QueryRows(&items)
+	if err != nil {
+		return nil, err
+	}
+	return
+}
+
+// UpdateLyIndexEdbExist 指标库标记已添加
+func UpdateLyIndexEdbExist(indexCode string, isExist int) (err error) {
+	o := orm.NewOrmUsingDB("data")
+
+	// 构建 SQL 更新语句
+	sql := `UPDATE base_from_ly_index SET edb_exist = ? WHERE index_code = ?`
+
+	// 执行 SQL 语句
+	_, err = o.Raw(sql, isExist, indexCode).Exec()
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+// GetLyIndexList 根据传入条件查询指标列表
+func GetLyIndexList(condition string, pars interface{}) (items []*BaseFromLyIndex, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT * FROM base_from_ly_index WHERE 1=1  `
+	if condition != "" {
+		sql += condition
+	}
+	sql += `ORDER BY base_from_ly_index_id ASC `
+	_, err = o.Raw(sql, pars).QueryRows(&items)
+	return
+}
+
+// GetLyDataMaxCount 获取分类下指标最大数据量
+func GetLyDataMaxCount(classifyId int) (count int, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT MAX(t.num) AS count FROM (
+				SELECT COUNT(1) AS num  FROM base_from_ly_index AS a
+				INNER JOIN base_from_ly_data AS b ON a.base_from_ly_index_id=b.base_from_ly_index_id
+				WHERE a.base_from_ly_classify_id=?
+				GROUP BY a.base_from_ly_index_id
+			)AS t `
+	err = o.Raw(sql, classifyId).QueryRow(&count)
+	return
+}
+
+// GetLyIndexByCodeAndClassify 根据指标编码和分类查询 indexCode非必传
+func GetLyIndexByCodeAndClassify(indexCode string, classifyId int, frequency *string) (items []*BaseFromLyIndex, err error) {
+	o := orm.NewOrmUsingDB("data")
+
+	// SQL 查询语句
+	sql := `SELECT a.index_code, a.index_name, a.frequency, a.unit, MAX(b.modify_time) AS modify_time
+			FROM base_from_ly_index AS a
+			INNER JOIN base_from_ly_data AS b ON a.base_from_ly_index_id = b.base_from_ly_index_id
+			WHERE 1=1`
+
+	var params []interface{}
+
+	if classifyId != 0 {
+		sql += ` AND a.base_from_ly_classify_id = ?`
+		params = append(params, classifyId)
+	}
+
+	// 如果 indexCode 不为空,增加过滤条件
+	if indexCode != "" {
+		sql += ` AND a.index_code = ?`
+		params = append(params, indexCode)
+	}
+
+	if frequency != nil {
+		sql += ` AND a.frequency = ?`
+		params = append(params, *frequency)
+	}
+
+	sql += ` GROUP BY a.index_code, a.index_name, a.frequency, a.unit`
+
+	_, err = o.Raw(sql, params...).QueryRows(&items)
+	if err != nil {
+		return nil, err
+	}
+	return
+}
+
+// GetLyIndexFrequency 获取指标频度
+func GetLyIndexFrequency(classifyId int) (items []*string, err error) {
+	sql := `SELECT DISTINCT frequency 
+        FROM base_from_ly_index 
+        WHERE frequency IS NOT NULL`
+
+	// 如果 classifyId > 0,则添加该条件
+	if classifyId > 0 {
+		sql += ` AND base_from_ly_classify_id = ?`
+	}
+
+	sql += ` ORDER BY FIELD(frequency, '日度', '周度', '月度', '季度', '半年度', '年度')`
+
+	o := orm.NewOrmUsingDB("data")
+	if classifyId > 0 {
+		_, err = o.Raw(sql, classifyId).QueryRows(&items)
+	} else {
+		_, err = o.Raw(sql).QueryRows(&items)
+	}
+
+	return items, err
+}

+ 2 - 2
models/data_manage/base_from_sci_hq_classify.go

@@ -137,14 +137,14 @@ func GetSciHqClassifyCountByName(classifyName string, lang string) (count int, e
 
 func GetBaseFromSciHqClassifyEnCount(classifyNameEn string, parentId int) (count int, err error) {
 	o := orm.NewOrmUsingDB("data")
-	sql := `SELECT COUNT(1) AS count FROM base_from_sci_classify WHERE classify_name_en=? AND parent_id=? `
+	sql := `SELECT COUNT(1) AS count FROM base_from_sci_hq_classify WHERE classify_name_en=? AND parent_id=? `
 	err = o.Raw(sql, classifyNameEn, parentId).QueryRow(&count)
 	return
 }
 
 func GetBaseFromSciHqClassifyCount(classifyName string, parentId int) (count int, err error) {
 	o := orm.NewOrmUsingDB("data")
-	sql := `SELECT COUNT(1) AS count FROM base_from_sci_classify WHERE classify_name=? AND parent_id=? `
+	sql := `SELECT COUNT(1) AS count FROM base_from_sci_hq_classify WHERE classify_name=? AND parent_id=? `
 	err = o.Raw(sql, classifyName, parentId).QueryRow(&count)
 	return
 }

+ 32 - 29
models/data_manage/base_from_sci_hq_index.go

@@ -8,15 +8,17 @@ import (
 )
 
 type BaseFromSciHqIndex struct {
-	BaseFromSciHqIndexId int    `orm:"pk"`
-	ClassifyId           int    `description:"指标分类id"`
-	IndexCode            string `description:"指标编码"`
-	IndexName            string `description:"指标名称"`
-	Unit                 string `description:"单位"`
-	Frequency            string `description:"频度"`
-	StartDate            string `description:"开始日期"`
-	EndDate              string
-	Sort                 int
+	BaseFromSciHqIndexId int       `orm:"pk"`
+	ClassifyId           int       `description:"指标分类id"`
+	IndexCode            string    `description:"指标编码"`
+	IndexName            string    `description:"指标名称"`
+	Unit                 string    `description:"单位"`
+	Frequency            string    `description:"频度"`
+	StartDate            string    `description:"开始日期"`
+	EndDate              string    `description:"结束日期"`
+	Sort                 int       `description:"排序"`
+	LatestValue          float64   `description:"最新值"`
+	LatestDate           time.Time `description:"最后更新时间"`
 	TerminalCode         string
 	FilePath             string `json:"-"`
 	CreateTime           time.Time
@@ -24,18 +26,20 @@ type BaseFromSciHqIndex struct {
 }
 
 type BaseFromSciHqIndexView struct {
-	BaseFromSciHqIndexId int    `orm:"pk"`
-	EdbInfoId            int    `description:"指标库id"`
-	ClassifyId           int    `description:"指标分类id"`
-	IndexCode            string `description:"指标编码"`
-	IndexName            string `description:"指标名称"`
-	UniqueCode           string `description:"唯一code"`
-	Frequency            string `description:"频度"`
-	Unit                 string `description:"单位"`
-	StartDate            string `description:"开始日期"`
-	EndDate              string `description:"结束日期"`
-	Sort                 int    `description:"排序"`
-	EdbExist             int    `description:"edb是否存在"`
+	BaseFromSciHqIndexId int     `orm:"pk"`
+	EdbInfoId            int     `description:"指标库id"`
+	ClassifyId           int     `description:"指标分类id"`
+	IndexCode            string  `description:"指标编码"`
+	IndexName            string  `description:"指标名称"`
+	UniqueCode           string  `description:"唯一code"`
+	Frequency            string  `description:"频度"`
+	Unit                 string  `description:"单位"`
+	StartDate            string  `description:"开始日期"`
+	EndDate              string  `description:"结束日期"`
+	Sort                 int     `description:"排序"`
+	LatestValue          float64 `description:"最新值"`
+	LatestDate           string  `description:"最后更新时间"`
+	EdbExist             int     `description:"edb是否存在"`
 	ModifyTime           string
 }
 
@@ -198,15 +202,14 @@ func GetSciHqIndexBaseInfoByCondition(condition string, pars []interface{}) (ite
 	return
 }
 
-func GetSciHqDataMaxCount(classifyId int) (count int, err error) {
+func GetSciHqDataMaxCount(condition string, pars []interface{}) (count int, err error) {
 	o := orm.NewOrmUsingDB("data")
-	sql := `SELECT MAX(t.num) AS count FROM (
-				SELECT COUNT(1) AS num  FROM base_from_sci_hq_index AS a
-				INNER JOIN base_from_sci_hq_data AS b ON a.index_code=b.index_code
-				WHERE a.classify_id=?
-				GROUP BY a.base_from_sci_hq_index_id
-			)AS t `
-	err = o.Raw(sql, classifyId).QueryRow(&count)
+	sql := `SELECT MAX(t.num) AS count FROM ( SELECT COUNT(1) AS num  FROM base_from_sci_hq_index AS a INNER JOIN base_from_sci_hq_data AS b ON a.index_code=b.index_code WHERE 1=1  `
+	if condition != "" {
+		sql += condition
+	}
+	sql += ` GROUP BY a.base_from_sci_hq_index_id) AS t `
+	err = o.Raw(sql, pars).QueryRow(&count)
 	return
 }
 

+ 154 - 3
models/data_manage/chart_info_range_analysis.go

@@ -28,7 +28,16 @@ type ChartRangeAnalysisExtraConf struct {
 type ChartRangeAnalysisAutoDateChangeConf struct {
 	BaseDateType int `description:"基准日期类型:0指标日期,1系统日期"`
 	MoveForward  int `description:"前移的期数"`
-	DateChange   []*EdbDateConfDateChange
+	DateChange   []*EdbDataDateChangeConf
+}
+
+type EdbDataDateChangeConf struct {
+	Year         int
+	Month        int
+	Day          int
+	Frequency    string `description:"频度变换"`
+	FrequencyDay string `description:"频度的固定日期"`
+	ChangeType   int    `description:"日期变换类型1日期位移,2指定频率"`
 }
 
 type ChartRangeAnalysisDeleteDataConf struct {
@@ -143,25 +152,41 @@ func EditRangeChartInfoAndMapping(req *EditChartInfoReq, edbInfoIdStr, lang stri
 	}()
 	var pars []interface{}
 	pars = append(pars, req.ChartName)
+	pars = append(pars, req.ChartNameEn)
 	pars = append(pars, edbInfoIdStr)
 	pars = append(pars, req.ChartType)
 	pars = append(pars, req.ChartClassifyId)
 	pars = append(pars, disabled)
 	pars = append(pars, barChartConf)
 	pars = append(pars, req.ExtraConfig)
+	pars = append(pars, req.StartYear)
+	pars = append(pars, req.ChartThemeId)
 	pars = append(pars, req.SourcesFrom)
+	pars = append(pars, req.Instructions)
+	pars = append(pars, req.MarkersLines)
+	pars = append(pars, req.MarkersAreas)
+	pars = append(pars, req.Unit)
+	pars = append(pars, req.UnitEn)
 
 	sql := ` UPDATE  chart_info
 			SET
 			  chart_name =?,
+			  chart_name_en =?,
               edb_info_ids=?,
 			  chart_type=?,
 			  chart_classify_id = ?,
 			  modify_time = NOW(),
               disabled = ?,
               bar_config = ?,
-			  extra_config = ?,
-			  sources_from = ?
+              extra_config = ?, 
+ 			  start_year = ?,
+ 			  chart_theme_id = ?,
+ 			  sources_from = ?,
+ 			  instructions = ?,
+ 			  markers_lines = ?,
+ 			  markers_areas = ?,
+ 			  unit = ?,
+ 			  unit_en = ?
 			`
 	if calendar != "" {
 		sql += `,calendar = ? `
@@ -196,6 +221,15 @@ func EditRangeChartInfoAndMapping(req *EditChartInfoReq, edbInfoIdStr, lang stri
 	sql += `,right_max = ? `
 	pars = append(pars, req.RightMax)
 
+	sql += `,right2_min = ? `
+	pars = append(pars, req.Right2Min)
+
+	sql += `,right2_max = ? `
+	pars = append(pars, req.Right2Max)
+
+	sql += `,min_max_save = ? `
+	pars = append(pars, req.MinMaxSave)
+
 	sql += `WHERE chart_info_id = ?`
 
 	pars = append(pars, req.ChartInfoId)
@@ -277,6 +311,72 @@ func EditRangeChartInfoAndMapping(req *EditChartInfoReq, edbInfoIdStr, lang stri
 	return
 }
 
+// EditRangeChartInfo 修改区间计算图表基本信息
+func EditRangeChartInfo(req *SaveChartRangeReq) (err error) {
+	o := orm.NewOrmUsingDB("data")
+	to, err := o.Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = to.Rollback()
+		} else {
+			_ = to.Commit()
+		}
+	}()
+	var pars []interface{}
+	pars = append(pars, req.StartYear)
+
+	sql := ` UPDATE  chart_info
+			SET
+			  modify_time = NOW(),
+ 			  start_year = ?
+			`
+	if req.DateType > 0 {
+		sql += `,date_type = ? `
+		pars = append(pars, req.DateType)
+	}
+
+	sql += `,start_date = ? `
+	pars = append(pars, req.StartDate)
+
+	sql += `,end_date = ? `
+	pars = append(pars, req.EndDate)
+
+	sql += `,left_min = ? `
+	pars = append(pars, req.LeftMin)
+
+	sql += `,left_max = ? `
+	pars = append(pars, req.LeftMax)
+
+	sql += `,right_min = ? `
+	pars = append(pars, req.RightMin)
+
+	sql += `,right_max = ? `
+	pars = append(pars, req.RightMax)
+
+	sql += `,right2_min = ? `
+	pars = append(pars, req.Right2Min)
+
+	sql += `,right2_max = ? `
+	pars = append(pars, req.Right2Max)
+
+	sql += `,min_max_save = ? `
+	pars = append(pars, req.MinMaxSave)
+
+	sql += `WHERE chart_info_id = ?`
+
+	pars = append(pars, req.ChartInfoId)
+	_, err = to.Raw(sql, pars).Exec()
+	if err != nil {
+		fmt.Println("UPDATE  chart_info Err:", err.Error())
+		return err
+	}
+
+	return
+}
+
 // SaveChartRangeAnalysisEdbReq 指标保存请求
 type SaveChartRangeAnalysisEdbReq struct {
 	EdbInfoList           []*CalculateEdbInfoItem `description:"指标列表"`
@@ -285,3 +385,54 @@ type SaveChartRangeAnalysisEdbReq struct {
 	IsSaveAs              bool `description:"是否另存为,true的话,就是另存为,不会建立与配置的关系"`
 	EdbInfoType           int  `description:"指标类型"`
 }
+
+// ChartRangeAnalysisConfigEdbResp 指标列表
+type ChartRangeAnalysisConfigEdbResp struct {
+	EdbInfoList []*ChartRangeAnalysisConfigEdbItem `description:"指标列表"`
+}
+
+type ChartRangeAnalysisConfigEdbItem struct {
+	EdbInfoId     int    `description:"指标id"`
+	EdbName       string `description:"指标名称"`
+	EdbNameEn     string `description:"指标名称"`
+	Frequency     string `description:"频度"`
+	Unit          string `description:"单位"`
+	UnitEn        string `description:"单位"`
+	ClassifyId    int    `description:"分类id"`
+	FromEdbInfoId int    `description:"计算来源指标id"`
+	EdbTypeInfo   int    `description:"指标类型,0普通指标,1预测指标"`
+}
+
+type SortEdbDataList []*EdbDataList
+
+func (m SortEdbDataList) Len() int {
+	return len(m)
+}
+
+func (m SortEdbDataList) Less(i, j int) bool {
+	return m[i].DataTime > m[j].DataTime
+}
+
+func (m SortEdbDataList) Swap(i, j int) {
+	m[i], m[j] = m[j], m[i]
+}
+
+type EditChartRangeBaseReq struct {
+	ChartInfoId int    `description:"图表ID"`
+	ChartName   string `description:"英文图表名称"`
+}
+type SaveChartRangeReq struct {
+	ChartInfoId int    `description:"图表ID"`
+	DateType    int    `description:"日期类型:1:00年至今,2:10年至今,3:15年至今,4:年初至今,5:自定义时间,6:起始日期至今,20:N年至今"`
+	StartDate   string `description:"自定义开始日期"`
+	EndDate     string `description:"自定义结束日期"`
+	Calendar    string `description:"公历/农历"`
+	LeftMin     string `description:"图表左侧最小值"`
+	LeftMax     string `description:"图表左侧最大值"`
+	RightMin    string `description:"图表右侧最小值"`
+	RightMax    string `description:"图表右侧最大值"`
+	Right2Min   string `description:"图表右侧最小值"`
+	Right2Max   string `description:"图表右侧最大值"`
+	MinMaxSave  int    `description:"是否手动保存过上下限:0-否;1-是"`
+	StartYear   int    `description:"当选择的日期类型为最近N年类型时,即date_type=20, 用start_year表示N"`
+}

+ 7 - 2
models/data_manage/edb_data_base.go

@@ -4,10 +4,11 @@ import (
 	"eta/eta_api/models/mgo"
 	"eta/eta_api/utils"
 	"fmt"
-	"github.com/beego/beego/v2/client/orm"
-	"go.mongodb.org/mongo-driver/bson"
 	"strconv"
 	"time"
+
+	"github.com/beego/beego/v2/client/orm"
+	"go.mongodb.org/mongo-driver/bson"
 )
 
 // GetEdbDataTableName 指标数据->存储表
@@ -176,6 +177,10 @@ func GetEdbDataTableName(source, subSource int) (tableName string) {
 		tableName = "edb_data_icpi"
 	case utils.DATA_SOURCE_SCI99: //ICPI消费价格指数->85
 		tableName = "edb_data_sci99"
+	case utils.DATA_SOURCE_SCI_HQ:
+		tableName = "edb_data_sci_hq"
+	case utils.DATA_SOURCE_LY: // 粮油商务网->86
+		tableName = "edb_data_ly"
 	default:
 		edbSource := EdbSourceIdMap[source]
 		if edbSource != nil {

+ 10 - 0
models/data_manage/edb_data_sci_hq.go

@@ -0,0 +1,10 @@
+package data_manage
+
+import "github.com/beego/beego/v2/client/orm"
+
+func GetEdbDataSciHqMaxAndMinDate(edbCode string) (min_date, max_date string, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT MIN(data_time) AS min_date,MAX(data_time) AS max_date FROM edb_data_sci_hq WHERE edb_code=? `
+	err = o.Raw(sql, edbCode).QueryRow(&min_date, &max_date)
+	return
+}

+ 2 - 2
models/data_manage/factor_edb_series_calculate_data_qjjs.go

@@ -37,8 +37,8 @@ type FactorEdbSeriesCalculateDataQjjsCols struct {
 	DataTimestamp     string
 }
 
-func (m *FactorEdbSeriesCalculateDataQjjs) Cols() FactorEdbSeriesCalculateDataCols {
-	return FactorEdbSeriesCalculateDataCols{
+func (m *FactorEdbSeriesCalculateDataQjjs) Cols() FactorEdbSeriesCalculateDataQjjsCols {
+	return FactorEdbSeriesCalculateDataQjjsCols{
 		PrimaryId:         "factor_edb_series_calculate_data_id",
 		FactorEdbSeriesId: "factor_edb_series_id",
 		EdbInfoId:         "edb_info_id",

+ 1 - 1
models/data_manage/multiple_graph_config_edb_mapping.go

@@ -70,7 +70,7 @@ func AddMultipleGraphConfigEdbMappingList(items []*MultipleGraphConfigEdbMapping
 
 func DeleteMultipleGraphConfigEdbMappingByEdbIds(configId, source int, edbIds []int) (err error) {
 	o := orm.NewOrmUsingDB("data")
-	sql := `DELETE FROM multiple_graph_config_edb_mapping WHERE multiple_graph_config_id = ? AND source = ? AND edb_id IN (` + utils.GetOrmInReplace(len(edbIds)) + `) `
+	sql := `DELETE FROM multiple_graph_config_edb_mapping WHERE multiple_graph_config_id = ? AND source = ? AND edb_info_id IN (` + utils.GetOrmInReplace(len(edbIds)) + `) `
 	_, err = o.Raw(sql, configId, source, edbIds).Exec()
 	return
 }

+ 19 - 1
models/target.go

@@ -1057,7 +1057,25 @@ func GetEdbDataFrequency(classifyId int) (items []*string, err error) {
 	return
 }
 
-func GetEdbDataFrequencyByKeyord(keyword string) (items []*string, err error) {
+// GetEdbDataFrequencyByClassifyIdList
+// @Description: 根据分类列表获取所有的频度
+// @author: Roc
+// @datetime 2024-08-15 17:51:13
+// @param classifyIdList []int
+// @return items []*string
+// @return err error
+func GetEdbDataFrequencyByClassifyIdList(classifyIdList []int) (items []string, err error) {
+	num := len(classifyIdList)
+	if num <= 0 {
+		return
+	}
+	sql := `SELECT DISTINCT frequency FROM edbinfo where classify_id in (` + utils.GetOrmInReplace(num) + `) AND frequency IS NOT NULL ORDER BY FIELD(frequency,'日度','周度','月度','季度','半年度','年度') `
+	o := orm.NewOrmUsingDB("edb")
+	_, err = o.Raw(sql, classifyIdList).QueryRows(&items)
+	return
+}
+
+func GetEdbDataFrequencyByKeyord(keyword string) (items []string, err error) {
 	sql := `SELECT DISTINCT frequency FROM edbinfo where SEC_NAME=? ORDER BY FIELD(frequency,'日度','周度','月度','季度','半年度','年度') `
 	o := orm.NewOrmUsingDB("edb")
 	_, err = o.Raw(sql, keyword).QueryRows(&items)

+ 91 - 1
routers/commentsRouter.go

@@ -2068,6 +2068,15 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/range_analysis:RangeChartChartInfoController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/range_analysis:RangeChartChartInfoController"],
+        beego.ControllerComments{
+            Method: "BaseInfoEdit",
+            Router: `/chart_info/base/edit`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/range_analysis:RangeChartChartInfoController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/range_analysis:RangeChartChartInfoController"],
         beego.ControllerComments{
             Method: "Copy",
@@ -2131,6 +2140,33 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/range_analysis:RangeChartChartInfoController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/range_analysis:RangeChartChartInfoController"],
+        beego.ControllerComments{
+            Method: "ChartInfoSave",
+            Router: `/chart_info/save`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/range_analysis:RangeChartChartInfoController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/range_analysis:RangeChartChartInfoController"],
+        beego.ControllerComments{
+            Method: "SearchByEs",
+            Router: `/chart_info/search_by_es`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/range_analysis:RangeChartChartInfoController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/range_analysis:RangeChartChartInfoController"],
+        beego.ControllerComments{
+            Method: "MultipleGraphConfigEdbList",
+            Router: `/edb/list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/range_analysis:RangeChartChartInfoController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/range_analysis:RangeChartChartInfoController"],
         beego.ControllerComments{
             Method: "MultipleGraphConfigSaveEdb",
@@ -2410,6 +2446,60 @@ func init() {
             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",
+            Router: `/ly/classify/list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:BaseFromLyIndexController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:BaseFromLyIndexController"],
+        beego.ControllerComments{
+            Method: "LyIndexAdd",
+            Router: `/ly/index/add`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:BaseFromLyIndexController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:BaseFromLyIndexController"],
+        beego.ControllerComments{
+            Method: "LyIndexAddValidate",
+            Router: `/ly/index/add/validate`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:BaseFromLyIndexController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:BaseFromLyIndexController"],
+        beego.ControllerComments{
+            Method: "LyIndexDataExport",
+            Router: `/ly/index/data/export`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:BaseFromLyIndexController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:BaseFromLyIndexController"],
+        beego.ControllerComments{
+            Method: "LyIndexDataList",
+            Router: `/ly/index/data/list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:BaseFromLyIndexController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:BaseFromLyIndexController"],
+        beego.ControllerComments{
+            Method: "LyIndexList",
+            Router: `/ly/index/list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:BaseFromNationalStatisticsController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:BaseFromNationalStatisticsController"],
         beego.ControllerComments{
             Method: "ClassifyList",
@@ -5807,7 +5897,7 @@ func init() {
         beego.ControllerComments{
             Method: "ExportSciHqList",
             Router: `/export/sciHqList`,
-            AllowHTTPMethods: []string{"post"},
+            AllowHTTPMethods: []string{"get"},
             MethodParams: param.Make(),
             Filters: nil,
             Params: nil})

+ 2 - 0
routers/router.go

@@ -177,6 +177,8 @@ func init() {
 				&data_manage.FactorEdbSeriesController{},
 				&data_manage.SciHqDataController{},
 				&data_manage.BaseFromThsHfController{},
+				&data_manage.BaseFromLyClassifyController{},
+				&data_manage.BaseFromLyIndexController{},
 			),
 		),
 		web.NSNamespace("/my_chart",

+ 6 - 0
services/data/base_edb_lib.go

@@ -76,6 +76,8 @@ func AddEdbData(source int, edbCode, frequency string) (resp *models.BaseRespons
 		urlStr = "sci99/add"
 	case utils.DATA_SOURCE_SCI_HQ:
 		urlStr = "sci_hq/add"
+	case utils.DATA_SOURCE_LY:
+		urlStr = "ly/add"
 	default:
 		edbSource := data_manage.EdbSourceIdMap[source]
 		if edbSource != nil {
@@ -272,6 +274,10 @@ func RefreshEdbData(edbInfoId, source, subSource int, edbCode, startDate string)
 		urlStr = "icpi/refresh"
 	case utils.DATA_SOURCE_SCI99:
 		urlStr = "sci99/refresh"
+	case utils.DATA_SOURCE_SCI_HQ:
+		urlStr = "sci_hq/refresh"
+	case utils.DATA_SOURCE_LY:
+		urlStr = "ly/refresh"
 	default:
 		edbSource := data_manage.EdbSourceIdMap[source]
 		if edbSource != nil {

+ 3 - 1
services/data/base_from_eia_steo.go

@@ -18,7 +18,9 @@ func GetClassifyALLById(classifyId int) (items []*data_manage.BaseFromEiaSteoCla
 			return
 		}
 		items = append(items, childClassify...)
-	} else {
+	}
+	// 兼容之前部分指标在一级分类下的情况
+	if len(items) == 0 {
 		items = append(items, classify)
 	}
 	return

+ 47 - 0
services/data/base_from_ly_classify_service.go

@@ -0,0 +1,47 @@
+// Package data
+// @Author gmy 2024/8/12 16:09:00
+package data
+
+import "eta/eta_api/models/data_manage"
+
+// LyClassifyList 获取分类列表 包含 分类下的指标名称
+func LyClassifyList() ([]*data_manage.BaseFromLyClassifyAndIndexInfo, error) {
+	// step_1 获取分类列表
+	lyClassify, err := data_manage.GetAllLyClassify()
+	if err != nil {
+		return nil, err
+	}
+	// step_2 分类id列表
+	classifyIds := make([]int, 0)
+	for _, v := range lyClassify {
+		classifyIds = append(classifyIds, v.BaseFromLyClassifyId)
+	}
+	// step_3 获取分类下的指标
+	lyIndices, err := data_manage.GetLyIndexByClassifyIds(classifyIds)
+	if err != nil {
+		return nil, err
+	}
+	// step_4 封装返回
+	lyClassifyAndIndexInfos := make([]*data_manage.BaseFromLyClassifyAndIndexInfo, 0)
+	for _, classify := range lyClassify {
+		lyClassifyAndIndexInfo := &data_manage.BaseFromLyClassifyAndIndexInfo{
+			BaseFromLyClassifyId: classify.BaseFromLyClassifyId,
+			CreateTime:           classify.CreateTime,
+			ModifyTime:           classify.ModifyTime,
+			ClassifyName:         classify.ClassifyName,
+			ParentId:             classify.ParentId,
+			Sort:                 classify.Sort,
+			ClassifyNameEn:       classify.ClassifyNameEn,
+		}
+		for _, lyIndex := range lyIndices {
+			if classify.BaseFromLyClassifyId == lyIndex.BaseFromLyClassifyId {
+				lyClassifyAndIndexInfo.IndexId = lyIndex.BaseFromLyIndexId
+				lyClassifyAndIndexInfo.IndexCode = lyIndex.IndexCode
+				lyClassifyAndIndexInfo.IndexName = lyIndex.IndexName
+			}
+		}
+		lyClassifyAndIndexInfos = append(lyClassifyAndIndexInfos, lyClassifyAndIndexInfo)
+	}
+
+	return lyClassifyAndIndexInfos, nil
+}

+ 222 - 0
services/data/base_from_ly_index_service.go

@@ -0,0 +1,222 @@
+// Package data
+// @Author gmy 2024/8/12 16:44:00
+package data
+
+import (
+	"eta/eta_api/models/data_manage"
+	"eta/eta_api/utils"
+	"fmt"
+	"github.com/beego/beego/v2/core/logs"
+	"github.com/rdlucklib/rdluck_tools/paging"
+)
+
+// GetIndexPage 获取指标分页列表
+func GetIndexPage(classifyId string, searchParam string, currentIndex, pageSize int) (*data_manage.BaseFromLyIndexPage, error) {
+	count, err := data_manage.GetLyIndexCount(classifyId, searchParam)
+	if err != nil {
+		return nil, err
+	}
+	lyIndexPage := data_manage.BaseFromLyIndexPage{}
+	page := paging.GetPaging(currentIndex, pageSize, count)
+
+	if count <= 0 {
+		lyIndexPage.Paging = page
+		return &lyIndexPage, nil
+	}
+
+	lyIndexList, err := data_manage.GetLyIndexPage(classifyId, searchParam, currentIndex, pageSize)
+	if err != nil {
+		return nil, err
+	}
+
+	// 获取指标编码列表
+	var indexCodes []string
+	for _, v := range lyIndexList {
+		indexCodes = append(indexCodes, v.IndexCode)
+	}
+	// 获取指标数据
+	lyIndexData, err := data_manage.GetLyDataLastByIndexCode(indexCodes)
+	if err != nil {
+		return nil, err
+	}
+	// 将lyIndexData转换为map
+	lyIndexDataMap := make(map[string]*data_manage.BaseFromLyData)
+	for _, v := range lyIndexData {
+		lyIndexDataMap[v.IndexCode] = v
+	}
+	if len(lyIndexData) > 0 {
+		for _, v := range lyIndexList {
+			if lyIndexDataMap[v.IndexCode] != nil {
+				v.Value = lyIndexDataMap[v.IndexCode].Value
+				toYmd := utils.TimeFormatToYmd(lyIndexDataMap[v.IndexCode].ModifyTime)
+				v.ModifyTimeMax = toYmd
+			}
+		}
+	}
+
+	lyIndexPage.List = lyIndexList
+	lyIndexPage.Paging = page
+
+	return &lyIndexPage, nil
+}
+
+// GetIndexDataPage 获取指标分页数据列表
+func GetIndexDataPage(indexId, startSize, pageSize int) (*data_manage.BaseFromLyDataPage, error) {
+	count, err := data_manage.GetLyDataCountByIndexId(indexId)
+	if err != nil {
+		return nil, err
+	}
+	lyDataPage := data_manage.BaseFromLyDataPage{}
+	page := paging.GetPaging(startSize, pageSize, count)
+
+	if count <= 0 {
+		lyDataPage.Paging = page
+		return &lyDataPage, nil
+	}
+
+	dataList, err := data_manage.GetLyDataPageByIndexId(indexId, startSize, pageSize)
+	if err != nil {
+		return nil, err
+	}
+	lyDataPage.List = dataList
+	lyDataPage.Paging = page
+
+	return &lyDataPage, nil
+}
+
+// LyIndexAddValidate 指标添加校验
+func LyIndexAddValidate(indexCodes []string) (*[]data_manage.IndexCheckData, error) {
+	// 根据指标编码获取指标库 指标信息
+	edbInfos, err := data_manage.GetEdbInfoByEdbCodeList(utils.DATA_SOURCE_LY, indexCodes)
+	if err != nil {
+		return nil, err
+	}
+	var respList []data_manage.IndexCheckData
+	if len(edbInfos) > 0 {
+		for _, ebdInfo := range edbInfos {
+			respList = append(respList, data_manage.IndexCheckData{
+				IndexCode:  ebdInfo.EdbCode,
+				IndexName:  ebdInfo.EdbName,
+				Unit:       ebdInfo.Unit,
+				Frequency:  ebdInfo.Frequency,
+				EdbInfoId:  ebdInfo.EdbInfoId,
+				ClassifyId: ebdInfo.ClassifyId,
+				UniqueCode: ebdInfo.UniqueCode,
+			})
+		}
+	}
+	return &respList, nil
+}
+
+// LyIndexNameCheck 指标名称校验
+func LyIndexNameCheck(indexNames []string, resp []*data_manage.NameCheckResult) ([]*data_manage.NameCheckResult, error) {
+	// 重名校验
+	edbList, e := data_manage.GetEdbInfoByNameArr(indexNames, utils.EDB_INFO_TYPE)
+	if e != nil {
+		return nil, e
+	}
+	nameExists := make(map[string]bool)
+	for _, edbInfo := range edbList {
+		nameExists[edbInfo.EdbName] = true
+	}
+	if len(nameExists) > 0 {
+		for _, v := range resp {
+			v.Exist = nameExists[v.IndexName]
+		}
+	}
+	return resp, nil
+}
+
+type LyIndexAddReq struct {
+	EdbCode       string `description:"指标编码"`
+	EdbName       string `description:"指标名称"`
+	Frequency     string `description:"频度"`
+	Unit          string `description:"单位"`
+	ClassifyId    int    `description:"分类ID"`
+	AdminId       int    `description:"管理员ID"`
+	AdminRealName string `description:"管理员名称"`
+}
+
+// LyIndexAdd 批量添加指标
+func LyIndexAdd(req LyIndexAddReq, 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("BloombergIndexSource2Edb新增失败, Err: %s", err.Error())
+			logs.Info(tips)
+			utils.FileLog.Info(tips)
+		}
+	}()
+	source := utils.DATA_SOURCE_LY
+
+	// 是否已有指标数据
+	dataList, e := data_manage.GetEdbDataAllByEdbCode(req.EdbCode, source, utils.DATA_SUB_SOURCE_EDB, utils.EDB_DATA_LIMIT)
+	if e != nil {
+		err = fmt.Errorf("获取指标数据失败, Err: %s", e.Error())
+		return
+	}
+
+	// 新增指标数据
+	if len(dataList) == 0 {
+		res, e := AddEdbData(source, req.EdbCode, req.Frequency)
+		if e != nil {
+			err = fmt.Errorf("index_lib: 新增指标数据失败, Err: %s", e.Error())
+			return
+		}
+		if res == nil {
+			err = fmt.Errorf("index_lib: 新增指标数据失败, res nil")
+			return
+		}
+		if res.Ret != 200 {
+			err = fmt.Errorf("index_lib: 新增指标数据失败, Ret: %d", res.Ret)
+			return
+		}
+	}
+
+	// 是否新增过指标
+	exist, e := data_manage.GetEdbInfoByEdbCode(source, req.EdbCode)
+	if e != nil && e.Error() != utils.ErrNoRow() {
+		err = fmt.Errorf("获取指标是否存在失败, err: %s", e.Error())
+		return
+	}
+	if exist != nil {
+		skip = true
+		return
+	}
+
+	// 开始结束时间
+	var startDate, endDate string
+	minMax, e := data_manage.GetEdbInfoMaxAndMinInfo(source, utils.DATA_SUB_SOURCE_EDB, req.EdbCode)
+	if e != nil && e.Error() != utils.ErrNoRow() {
+		err = fmt.Errorf("MinMax: 获取指标极值失败, err: %s", e.Error())
+		return
+	}
+	if minMax != nil {
+		startDate = minMax.MinDate
+		endDate = minMax.MaxDate
+	}
+
+	// 新增指标到指标库
+	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
+
+	// 标记原始指标为已添加
+	err = data_manage.UpdateLyIndexEdbExist(req.EdbCode, utils.IS_YES)
+	if err != nil {
+		err = fmt.Errorf("BaseIndex: 标记已添加指标库失败, err: %s", err.Error())
+		return
+	}
+
+	// todo EdbInfoAdd方法已经新增es,这里不需要再新增???
+	// 新增es
+	// go AddOrEditEdbInfoToEs(edbInfo.EdbInfoId)
+	return
+}

+ 7 - 7
services/data/base_from_sci_hq.go

@@ -8,7 +8,7 @@ import (
 	"time"
 )
 
-func AddSciHqClassify(classifyName, lang string, parentId int) (ok bool, err error) {
+func AddSciHqClassify(classifyName, lang string, parentId int) (ok bool, msg string, err error) {
 	var count int
 	switch lang {
 	case utils.EnLangVersion:
@@ -20,20 +20,20 @@ func AddSciHqClassify(classifyName, lang string, parentId int) (ok bool, err err
 		return
 	}
 	if count > 0 {
-		return false, errors.New("分类已存在")
+		return false, "分类已存在", nil
 	}
 
 	sort, err := data_manage.GetChildSciHqClassifyMaxSortById(parentId)
 	if err != nil {
-		return false, err
+		return false, "", err
 	}
 	if parentId > 0 {
 		count, err = data_manage.GetSciHqClassifyCountById(parentId)
 		if err != nil {
-			return false, err
+			return false, "", err
 		}
 		if count == 0 {
-			return false, errors.New("父分类不存在")
+			return false, "", errors.New("父分类不存在")
 		}
 		sciHqClassify := &data_manage.BaseFromSciHqClassify{
 			ClassifyName:   classifyName,
@@ -60,7 +60,7 @@ func AddSciHqClassify(classifyName, lang string, parentId int) (ok bool, err err
 		}
 		insertId, er := sciHqClassify.Add()
 		if er != nil {
-			return false, er
+			return false, "", er
 		}
 		sciHqClassifyList := []*data_manage.BaseFromSciHqClassify{
 			{
@@ -105,7 +105,7 @@ func AddSciHqClassify(classifyName, lang string, parentId int) (ok bool, err err
 			return
 		}
 	}
-	return true, nil
+	return true, "", nil
 }
 
 func DelSciHqClassify(classifyId int) (err error) {

+ 10 - 0
services/data/edb_classify.go

@@ -903,6 +903,16 @@ func Delete(classifyId, edbInfoId int, sysUser *system.Admin, requestBody, reque
 			return
 		}
 
+		// 维护粮油数据源指标领取状态
+		if edbInfo.Source == utils.DATA_SOURCE_LY {
+			tmpErr = data_manage.UpdateLyIndexEdbExist(edbInfo.EdbCode, utils.IS_NO)
+			if err != nil {
+				errMsg = "删除失败"
+				err = errors.New("删除失败,Err:" + tmpErr.Error())
+				return
+			}
+		}
+
 		// 如果是同花顺高频数据或类似数据, 还需要删除base_from_edb_mapping对应关系
 		baseMappingOb := new(data_manage.BaseFromEdbMapping)
 		{

+ 1 - 0
services/data/edb_info.go

@@ -1833,6 +1833,7 @@ func EdbInfoAdd(source, subSource, classifyId int, edbCode, edbName, frequency,
 		utils.DATA_SOURCE_FUBAO:               "富宝数据",
 		utils.DATA_SOURCE_GFEX:                "广期所",
 		utils.DATA_SOURCE_SCI_HQ:              "卓创红期",
+		utils.DATA_SOURCE_LY:                  "粮油商务网",
 	}
 
 	sourceName, ok := sourceNameMap[source]

+ 368 - 142
services/data/range_analysis/chart_info.go

@@ -9,6 +9,7 @@ import (
 	"eta/eta_api/services/data"
 	"eta/eta_api/utils"
 	"fmt"
+	"github.com/shopspring/decimal"
 	"math"
 	"sort"
 	"strconv"
@@ -16,114 +17,353 @@ import (
 	"time"
 )
 
+// GetAutoCalculateDateDataList 获取当前时间相关的区间作为计算依据
+func GetAutoCalculateDateDataList(currentDate string, dataList []*data_manage.EdbDataList, req *data_manage.ChartRangeAnalysisExtraConf) (newDataList []*data_manage.EdbDataList, err error) {
+	currentDateTime, _ := time.ParseInLocation(utils.FormatDate, currentDate, time.Local)
+	switch req.DateRangeType {
+	case 0:
+		// 智能划分得到一个开始日期,和结束日期
+		var startDateTime time.Time
+		if req.AutoDateConf.IsAutoStartDate == 0 { //固定设置
+			startDate := req.AutoDateConf.StartDate
+			if startDate == "" {
+				startDate = "2020-01-01"
+			}
+			startDateTime, _ = time.ParseInLocation(utils.FormatDate, startDate, time.Local)
+		} else {
+			startConf := req.AutoDateConf.StartDateConf
+			startDate := ""
+			if startConf.BaseDateType == 0 { //
+				startDate = currentDate
+			} else if startConf.BaseDateType == 1 {
+				startDate = time.Now().Format(utils.FormatDate)
+			}
+			if startConf.MoveForward > 0 {
+				startDate = GetEdbDateByMoveForward(startDate, startConf.MoveForward, dataList)
+			}
+			if len(startConf.DateChange) > 0 {
+				startDate, err = HandleEdbDateChange(startDate, startConf.DateChange)
+				if err != nil {
+					err = fmt.Errorf("智能划分开始日期处理失败:%s", err.Error())
+					return
+				}
+			}
+			startDateTime, _ = time.ParseInLocation(utils.FormatDate, startDate, time.Local)
+		}
+		var calStartTime, calEndTime time.Time
+		if currentDateTime.Before(startDateTime) {
+			calStartTime = currentDateTime
+			calEndTime = startDateTime
+		} else {
+			calStartTime = startDateTime
+			calEndTime = currentDateTime
+		}
+		// 根据日期,获取数据
+		for _, vv := range dataList {
+			dataTimeT, _ := time.ParseInLocation(utils.FormatDate, vv.DataTime, time.Local)
+			if (dataTimeT.After(calStartTime) && dataTimeT.Before(calEndTime)) ||
+				dataTimeT.Equal(calStartTime) ||
+				dataTimeT.Equal(calEndTime) {
+				newDataList = append(newDataList, vv)
+			}
+		}
+	}
+	return
+}
+
 // HandleDataByCalculateType 根据计算公式处理数据
-func HandleDataByCalculateType(originList []*data_manage.ChartRangeAnalysisDateDataItem, calculateType int) (newList []*data_manage.EdbDataList, err error) {
+func HandleDataByCalculateType(originList []*data_manage.ChartRangeAnalysisDateDataItem, originDataList []*data_manage.EdbDataList, req *data_manage.ChartRangeAnalysisExtraConf) (newList []*data_manage.EdbDataList, err error) {
 	if len(originList) == 0 {
 		return
 	}
+	calculateType := req.CalculateType
 	switch calculateType {
 	case 0: //均值
 		var sum float64
-		for _, item := range originList {
-			sum = 0
-			for k, v := range item.DataList {
-				sum += v.Value
-				val := sum / float64(k+1)
-				newList = append(newList, &data_manage.EdbDataList{
-					DataTime:      v.DataTime,
-					Value:         val,
-					DataTimestamp: v.DataTimestamp,
-				})
+		if req.DateRangeType == 0 && req.AutoDateConf.IsAutoStartDate > 0 {
+			for _, item := range originList {
+				for _, v := range item.DataList {
+					sum = 0
+					//计算的数据返回需要重新确定
+					calDataList, e := GetAutoCalculateDateDataList(v.DataTime, originDataList, req)
+					if e != nil {
+						err = fmt.Errorf("获取区间数据失败:%s", e.Error())
+						return
+					}
+					for _, vv := range calDataList {
+						sum += vv.Value
+					}
+					val := sum / float64(len(calDataList))
+					val, _ = decimal.NewFromFloat(val).Round(4).Float64()
+					newList = append(newList, &data_manage.EdbDataList{
+						DataTime:      v.DataTime,
+						Value:         val,
+						DataTimestamp: v.DataTimestamp,
+					})
+				}
+			}
+		} else {
+			for _, item := range originList {
+				sum = 0
+				for k, v := range item.DataList {
+					sum += v.Value
+					val := sum / float64(k+1)
+					val, _ = decimal.NewFromFloat(val).Round(4).Float64()
+					newList = append(newList, &data_manage.EdbDataList{
+						DataTime:      v.DataTime,
+						Value:         val,
+						DataTimestamp: v.DataTimestamp,
+					})
+				}
 			}
 		}
+
 	case 1: //累计值
 		var sum float64
-		for _, item := range originList {
-			sum = 0
-			for _, v := range item.DataList {
-				sum += v.Value
-				val := sum
-				newList = append(newList, &data_manage.EdbDataList{
-					DataTime:      v.DataTime,
-					Value:         val,
-					DataTimestamp: v.DataTimestamp,
-				})
+		if req.DateRangeType == 0 && req.AutoDateConf.IsAutoStartDate > 0 {
+			for _, item := range originList {
+				sum = 0
+				for _, v := range item.DataList {
+					sum = 0
+					//计算的数据返回需要重新确定
+					calDataList, e := GetAutoCalculateDateDataList(v.DataTime, originDataList, req)
+					if e != nil {
+						err = fmt.Errorf("获取区间数据失败:%s", e.Error())
+						return
+					}
+					for _, vv := range calDataList {
+						sum += vv.Value
+					}
+					val := sum
+					val, _ = decimal.NewFromFloat(val).Round(4).Float64()
+					newList = append(newList, &data_manage.EdbDataList{
+						DataTime:      v.DataTime,
+						Value:         val,
+						DataTimestamp: v.DataTimestamp,
+					})
+				}
+			}
+		} else {
+			for _, item := range originList {
+				sum = 0
+				for _, v := range item.DataList {
+					sum += v.Value
+					val := sum
+					val, _ = decimal.NewFromFloat(val).Round(4).Float64()
+					newList = append(newList, &data_manage.EdbDataList{
+						DataTime:      v.DataTime,
+						Value:         val,
+						DataTimestamp: v.DataTimestamp,
+					})
+				}
 			}
 		}
+
 	case 2: //涨幅
-		for _, item := range originList {
-			var baseVal float64
-			for k, v := range item.DataList {
-				if k == 0 {
-					baseVal = v.Value
+		if req.DateRangeType == 0 && req.AutoDateConf.IsAutoStartDate > 0 {
+			for _, item := range originList {
+				for _, v := range item.DataList {
+					var baseVal float64
+					//计算的数据返回需要重新确定
+					calDataList, e := GetAutoCalculateDateDataList(v.DataTime, originDataList, req)
+					if e != nil {
+						err = fmt.Errorf("获取区间数据失败:%s", e.Error())
+						return
+					}
+					if len(calDataList) == 0 {
+						continue
+					}
+					baseVal = calDataList[len(calDataList)-1].Value
+					baseDate := calDataList[len(calDataList)-1].DataTime
 					if baseVal == 0 {
-						break
+						continue
+					}
+					if v.DataTime == baseDate {
+						continue
 					}
+
+					val := (v.Value - baseVal) / baseVal
+					val, _ = decimal.NewFromFloat(val).Round(4).Float64()
+					newList = append(newList, &data_manage.EdbDataList{
+						DataTime:      v.DataTime,
+						Value:         val,
+						DataTimestamp: v.DataTimestamp,
+					})
+				}
+			}
+		} else {
+			for _, item := range originList {
+				if len(item.DataList) == 0 {
+					break
+				}
+				baseVal := item.DataList[len(item.DataList)-1].Value
+				baseDate := item.DataList[len(item.DataList)-1].DataTime
+				if baseVal == 0 {
+					break
+				}
+				for _, v := range item.DataList {
+					if v.DataTime == baseDate {
+						continue
+					}
+					val := (v.Value - baseVal) / baseVal
+					val, _ = decimal.NewFromFloat(val).Round(4).Float64()
+					newList = append(newList, &data_manage.EdbDataList{
+						DataTime:      v.DataTime,
+						Value:         val,
+						DataTimestamp: v.DataTimestamp,
+					})
 				}
-				val := (v.Value - baseVal) / baseVal
-				newList = append(newList, &data_manage.EdbDataList{
-					DataTime:      v.DataTime,
-					Value:         val,
-					DataTimestamp: v.DataTimestamp,
-				})
 			}
 		}
 	case 3: //复合增长率
-		for _, item := range originList {
-			var baseVal float64
-			var baseDate string
-			for k, v := range item.DataList {
-				if k == 0 {
-					baseVal = v.Value
-					baseDate = v.DataTime
+		if req.DateRangeType == 0 && req.AutoDateConf.IsAutoStartDate > 0 {
+			for _, item := range originList {
+				for _, v := range item.DataList {
+					var baseVal float64
+					var baseDate string
+					calDataList, e := GetAutoCalculateDateDataList(v.DataTime, originDataList, req)
+					if e != nil {
+						err = fmt.Errorf("获取区间数据失败:%s", e.Error())
+						return
+					}
+					if len(calDataList) == 0 {
+						continue
+					}
+					baseVal = calDataList[len(calDataList)-1].Value
+					baseDate = calDataList[len(calDataList)-1].DataTime
+					if v.DataTime == baseDate {
+						continue
+					}
 					if baseVal == 0 {
-						break
+						continue
+					}
+
+					baseDateT, e := time.ParseInLocation(utils.FormatDate, baseDate, time.Local)
+					if e != nil {
+						err = fmt.Errorf("time.ParseInLocation err: %v", e)
+						return
 					}
-					continue
+					tmpT, e := time.ParseInLocation(utils.FormatDate, v.DataTime, time.Local)
+					if e != nil {
+						err = fmt.Errorf("time.ParseInLocation err: %v", e)
+						return
+					}
+					// 计算两个日期相差的天数
+					diff := tmpT.Sub(baseDateT).Hours() / 24 / 365
+					val := v.Value / baseVal
+					val = math.Pow(val, 1/diff) - 1
+					val, _ = decimal.NewFromFloat(val).Round(4).Float64()
+					newList = append(newList, &data_manage.EdbDataList{DataTime: v.DataTime, Value: val, DataTimestamp: v.DataTimestamp})
 				}
-				baseDateT, e := time.ParseInLocation(utils.FormatDate, baseDate, time.Local)
-				if e != nil {
-					err = fmt.Errorf("time.ParseInLocation err: %v", e)
-					return
+			}
+		} else {
+			for _, item := range originList {
+				if len(item.DataList) == 0 {
+					break
 				}
-				tmpT, e := time.ParseInLocation(utils.FormatDate, baseDate, time.Local)
-				if e != nil {
-					err = fmt.Errorf("time.ParseInLocation err: %v", e)
-					return
+				baseVal := item.DataList[len(item.DataList)-1].Value
+				baseDate := item.DataList[len(item.DataList)-1].DataTime
+				if baseVal == 0 {
+					break
+				}
+				for _, v := range item.DataList {
+					if v.DataTime == baseDate {
+						continue
+					}
+					baseDateT, e := time.ParseInLocation(utils.FormatDate, baseDate, time.Local)
+					if e != nil {
+						err = fmt.Errorf("time.ParseInLocation err: %v", e)
+						return
+					}
+					tmpT, e := time.ParseInLocation(utils.FormatDate, v.DataTime, time.Local)
+					if e != nil {
+						err = fmt.Errorf("time.ParseInLocation err: %v", e)
+						return
+					}
+					// 计算两个日期相差的天数
+					diff := tmpT.Sub(baseDateT).Hours() / 24 / 365
+					val := v.Value / baseVal
+					val = math.Pow(val, 1/diff) - 1
+					val, _ = decimal.NewFromFloat(val).Round(4).Float64()
+					newList = append(newList, &data_manage.EdbDataList{DataTime: v.DataTime, Value: val, DataTimestamp: v.DataTimestamp})
 				}
-				// 计算两个日期相差的天数
-				diff := tmpT.Sub(baseDateT).Hours() / 24
-				val := v.Value / baseVal
-				val = math.Pow(val, diff) - 1
-				newList = append(newList, &data_manage.EdbDataList{DataTime: v.DataTime, Value: val, DataTimestamp: v.DataTimestamp})
 			}
 		}
 	case 4: //最大值
 		var maxVal float64
-		for _, item := range originList {
-			for k, v := range item.DataList {
-				if k == 0 {
-					maxVal = v.Value
+		if req.DateRangeType == 0 && req.AutoDateConf.IsAutoStartDate > 0 {
+			for _, item := range originList {
+				for _, v := range item.DataList {
+					calDataList, e := GetAutoCalculateDateDataList(v.DataTime, originDataList, req)
+					if e != nil {
+						err = fmt.Errorf("获取区间数据失败:%s", e.Error())
+						return
+					}
+					for kk, vv := range calDataList {
+						if kk == 0 {
+							maxVal = vv.Value
+						}
+						if vv.Value > maxVal {
+							maxVal = vv.Value
+						}
+					}
+
+					val := maxVal
+					val, _ = decimal.NewFromFloat(val).Round(4).Float64()
+					newList = append(newList, &data_manage.EdbDataList{DataTime: v.DataTime, Value: val, DataTimestamp: v.DataTimestamp})
 				}
-				if v.Value > maxVal {
-					maxVal = v.Value
+			}
+		} else {
+			for _, item := range originList {
+				for k, v := range item.DataList {
+					if k == 0 {
+						maxVal = v.Value
+					}
+					if v.Value > maxVal {
+						maxVal = v.Value
+					}
+					val := maxVal
+					val, _ = decimal.NewFromFloat(val).Round(4).Float64()
+					newList = append(newList, &data_manage.EdbDataList{DataTime: v.DataTime, Value: val, DataTimestamp: v.DataTimestamp})
 				}
-				val := maxVal
-				newList = append(newList, &data_manage.EdbDataList{DataTime: v.DataTime, Value: val, DataTimestamp: v.DataTimestamp})
 			}
 		}
 	case 5: //最小值
 		var minVal float64
-		for _, item := range originList {
-			for k, v := range item.DataList {
-				if k == 0 {
-					minVal = v.Value
+		if req.DateRangeType == 0 && req.AutoDateConf.IsAutoStartDate > 0 {
+			for _, item := range originList {
+				for _, v := range item.DataList {
+					calDataList, e := GetAutoCalculateDateDataList(v.DataTime, originDataList, req)
+					if e != nil {
+						err = fmt.Errorf("获取区间数据失败:%s", e.Error())
+						return
+					}
+					for kk, vv := range calDataList {
+						if kk == 0 {
+							minVal = vv.Value
+						}
+						if vv.Value < minVal {
+							minVal = vv.Value
+						}
+					}
+					val := minVal
+					val, _ = decimal.NewFromFloat(val).Round(4).Float64()
+					newList = append(newList, &data_manage.EdbDataList{DataTime: v.DataTime, Value: val, DataTimestamp: v.DataTimestamp})
 				}
-				if v.Value < minVal {
-					minVal = v.Value
+			}
+		} else {
+			for _, item := range originList {
+				for k, v := range item.DataList {
+					if k == 0 {
+						minVal = v.Value
+					}
+					if v.Value < minVal {
+						minVal = v.Value
+					}
+					val := minVal
+					val, _ = decimal.NewFromFloat(val).Round(4).Float64()
+					newList = append(newList, &data_manage.EdbDataList{DataTime: v.DataTime, Value: val, DataTimestamp: v.DataTimestamp})
 				}
-				val := minVal
-				newList = append(newList, &data_manage.EdbDataList{DataTime: v.DataTime, Value: val, DataTimestamp: v.DataTimestamp})
 			}
 		}
 	}
@@ -131,56 +371,6 @@ func HandleDataByCalculateType(originList []*data_manage.ChartRangeAnalysisDateD
 	return
 }
 
-// MoveDataDaysToNewDataList 平移指标数据生成新的数据序列
-func MoveDataDaysToNewDataList(dataList []*data_manage.EdbDataList, moveDay int) (newDataList []data_manage.EdbDataList, dateDataMap map[string]float64) {
-	dateMap := make(map[time.Time]float64)
-	var minDate, maxDate time.Time
-	dateDataMap = make(map[string]float64)
-
-	for _, v := range dataList {
-		currDate, _ := time.ParseInLocation(utils.FormatDate, v.DataTime, time.Local)
-		if minDate.IsZero() || currDate.Before(minDate) {
-			minDate = currDate
-		}
-		if maxDate.IsZero() || currDate.After(maxDate) {
-			maxDate = currDate
-		}
-		dateMap[currDate] = v.Value
-	}
-
-	// 处理领先、滞后数据
-	newDateMap := make(map[time.Time]float64)
-	for currDate, value := range dateMap {
-		newDate := currDate.AddDate(0, 0, moveDay)
-		newDateMap[newDate] = value
-	}
-	minDate = minDate.AddDate(0, 0, moveDay)
-	maxDate = maxDate.AddDate(0, 0, moveDay)
-
-	// 获取日期相差日
-	dayNum := utils.GetTimeSubDay(minDate, maxDate)
-
-	for i := 0; i <= dayNum; i++ {
-		currDate := minDate.AddDate(0, 0, i)
-		tmpValue, ok := newDateMap[currDate]
-		if !ok {
-			//找不到数据,那么就用前面的数据吧
-			if len(newDataList)-1 < 0 {
-				tmpValue = 0
-			} else {
-				tmpValue = newDataList[len(newDataList)-1].Value
-			}
-		}
-		tmpData := data_manage.EdbDataList{
-			DataTime: currDate.Format(utils.FormatDate),
-			Value:    tmpValue,
-		}
-		dateDataMap[tmpData.DataTime] = tmpData.Value
-		newDataList = append(newDataList, tmpData)
-	}
-	return
-}
-
 // GetChartEdbInfoFormat 区间计算图表-获取指标信息
 func GetChartEdbInfoFormat(chartInfoId int, edbInfoMappingList []*data_manage.ChartEdbInfoMapping) (edbList []*data_manage.ChartEdbInfoMapping, err error) {
 	edbList = make([]*data_manage.ChartEdbInfoMapping, 0)
@@ -224,6 +414,16 @@ func GetChartDataByEdbInfoList(chartInfoId int, dateType, startYear int, startDa
 		if err != nil {
 			return
 		}
+		edbInfoMapping.ConvertUnit = edbInfoMapping.Unit
+		edbInfoMapping.ConvertEnUnit = edbInfoMapping.UnitEn
+		if req.CalculateType == 2 || req.CalculateType == 3 {
+			edbInfoMapping.ConvertUnit = "无"
+			edbInfoMapping.ConvertEnUnit = "无"
+		}
+		if req.DataConvertType > 0 && req.DataConvertConf.Unit != "" {
+			edbInfoMapping.ConvertUnit = req.DataConvertConf.Unit
+			edbInfoMapping.ConvertEnUnit = req.DataConvertConf.Unit
+		}
 		dataList := edbInfoMapping.DataList.([]*data_manage.EdbDataList)
 		// 处理上下限
 		var maxData, minData float64
@@ -303,7 +503,7 @@ func GetChartDataByEdbInfoList(chartInfoId int, dateType, startYear int, startDa
 	}
 	dataResp = data_manage.ChartRangeAnalysisDataResp{ChartRangeAnalysisExtraConf: req}
 	if req.MultipleGraphConfigId > 0 {
-		multipleGraphConfigEdbMappingList, e := data_manage.GetMultipleGraphConfigEdbMappingListById(req.MultipleGraphConfigId)
+		multipleGraphConfigEdbMappingList, e := data_manage.GetMultipleGraphConfigEdbMappingListByIdAndSource(req.MultipleGraphConfigId, utils.CHART_SOURCE_RANGE_ANALYSIS)
 		if e != nil && e.Error() != utils.ErrNoRow() {
 			err = fmt.Errorf("获取区间计算图表, 指标信息失败, Err:" + e.Error())
 			return
@@ -341,6 +541,16 @@ func GetChartDataByEdbInfoListBySeries(chartInfoId int, dateType, startYear int,
 			err = e
 			return
 		}
+		edbInfoMapping.ConvertUnit = edbInfoMapping.Unit
+		edbInfoMapping.ConvertEnUnit = edbInfoMapping.UnitEn
+		if req.CalculateType == 2 || req.CalculateType == 3 {
+			edbInfoMapping.ConvertUnit = "无"
+			edbInfoMapping.ConvertEnUnit = "无"
+		}
+		if req.DataConvertType > 0 && req.DataConvertConf.Unit != "" {
+			edbInfoMapping.ConvertUnit = req.DataConvertConf.Unit
+			edbInfoMapping.ConvertEnUnit = req.DataConvertConf.Unit
+		}
 		edbInfoMapping.DataList = dataList
 		// 处理上下限
 		var maxData, minData float64
@@ -418,7 +628,7 @@ func GetChartDataByEdbInfoListBySeries(chartInfoId int, dateType, startYear int,
 	dataResp = data_manage.ChartRangeAnalysisDataResp{ChartRangeAnalysisExtraConf: req, SeriesId: seriesMappingItem.FactorEdbSeriesId}
 	// 查询配置关联关系
 	if req.MultipleGraphConfigId > 0 {
-		multipleGraphConfigEdbMappingList, e := data_manage.GetMultipleGraphConfigEdbMappingListById(req.MultipleGraphConfigId)
+		multipleGraphConfigEdbMappingList, e := data_manage.GetMultipleGraphConfigEdbMappingListByIdAndSource(req.MultipleGraphConfigId, utils.CHART_SOURCE_RANGE_ANALYSIS)
 		if e != nil && e.Error() != utils.ErrNoRow() {
 			err = fmt.Errorf("获取区间计算图表, 指标信息失败, Err:" + e.Error())
 			return
@@ -445,29 +655,32 @@ func getChartDataByEdbInfo(edbInfoMapping *data_manage.ChartEdbInfoMapping, req
 	edbEndDate := edbEndDateTime.AddDate(0, 0, 1).Format(utils.FormatDate)
 
 	// 获取时间基准指标在时间区间内的值
-	dataList := make([]*data_manage.EdbDataList, 0)
+	dataListTmp := make([]*data_manage.EdbDataList, 0)
 	switch edbInfoMapping.EdbInfoCategoryType {
 	case 0:
-		dataList, err = data_manage.GetEdbDataList(edbInfoMapping.Source, edbInfoMapping.SubSource, edbInfoMapping.EdbInfoId, "", "")
+		dataListTmp, err = data_manage.GetEdbDataList(edbInfoMapping.Source, edbInfoMapping.SubSource, edbInfoMapping.EdbInfoId, "", "")
 	case 1:
-		_, dataList, _, _, err, _ = data.GetPredictDataListByPredictEdbInfoId(edbInfoMapping.EdbInfoId, "", "", false)
+		_, dataListTmp, _, _, err, _ = data.GetPredictDataListByPredictEdbInfoId(edbInfoMapping.EdbInfoId, "", "", false)
 	default:
 		err = errors.New("指标base类型异常")
 		return
 	}
-
+	var dataList data_manage.SortEdbDataList
+	dataList = dataListTmp
+	sort.Sort(dataList)
 	dateList := make([]*data_manage.ChartRangeAnalysisDateDataItem, 0)
 	switch req.DateRangeType {
 	case 0:
 		// 智能划分得到一个开始日期,和结束日期
 		var startDateTime, endDateTime time.Time
+		startDateTime = edbStartDateTime
 		if req.AutoDateConf.IsAutoStartDate == 0 { //固定设置
 			startDate := req.AutoDateConf.StartDate
 			if startDate == "" {
 				startDate = "2020-01-01"
 			}
 			startDateTime, _ = time.ParseInLocation(utils.FormatDate, startDate, time.Local)
-		} else {
+		} /*else {
 			startConf := req.AutoDateConf.StartDateConf
 			startDate := ""
 			if startConf.BaseDateType == 0 { //
@@ -486,7 +699,7 @@ func getChartDataByEdbInfo(edbInfoMapping *data_manage.ChartEdbInfoMapping, req
 				}
 			}
 			startDateTime, _ = time.ParseInLocation(utils.FormatDate, startDate, time.Local)
-		}
+		}*/
 
 		if req.AutoDateConf.IsAutoEndDate == 0 { //固定设置
 			endDate := req.AutoDateConf.EndDate
@@ -500,7 +713,7 @@ func getChartDataByEdbInfo(edbInfoMapping *data_manage.ChartEdbInfoMapping, req
 			endConf := req.AutoDateConf.EndDateConf
 			endDate := edbEndDate
 			if endConf.MoveForward > 0 {
-				endDate = GetEdbDateByMoveForward(endConf.MoveForward, dataList)
+				endDate = GetEdbDateByMoveForward(endDate, endConf.MoveForward, dataList)
 			}
 			if len(endConf.DateChange) > 0 {
 				endDate, err = HandleEdbDateChange(endDate, endConf.DateChange)
@@ -560,7 +773,7 @@ func getChartDataByEdbInfo(edbInfoMapping *data_manage.ChartEdbInfoMapping, req
 		}
 	}
 	// 根据时间区间类型来获取数据的计算窗口,然后再拼接成整段数据
-	newDataList, err := HandleDataByCalculateType(dateList, req.CalculateType)
+	newDataList, err := HandleDataByCalculateType(dateList, dataList, req)
 	if err != nil {
 		return
 	}
@@ -587,13 +800,17 @@ func getChartDataByEdbInfo(edbInfoMapping *data_manage.ChartEdbInfoMapping, req
 		switch req.DataConvertType {
 		case 1:
 			for i, v := range newDataList {
-				newDataList[i].Value = v.Value * req.DataConvertConf.Value
+				val := v.Value * req.DataConvertConf.Value
+				val, _ = decimal.NewFromFloat(val).Round(4).Float64()
+				newDataList[i].Value = val
 			}
 			//item.MaxData = item.MaxData * v.ConvertValue
 			//item.MinData = item.MinData * v.ConvertValue
 		case 2:
 			for i, v := range newDataList {
-				newDataList[i].Value = v.Value / req.DataConvertConf.Value
+				val := v.Value / req.DataConvertConf.Value
+				val, _ = decimal.NewFromFloat(val).Round(4).Float64()
+				newDataList[i].Value = val
 			}
 			//item.MaxData = item.MaxData / v.ConvertValue
 			//item.MinData = item.MinData / v.ConvertValue
@@ -603,7 +820,9 @@ func getChartDataByEdbInfo(edbInfoMapping *data_manage.ChartEdbInfoMapping, req
 					err = errors.New("数据中含有负数或0,无法对数运算")
 					return
 				}
-				newDataList[i].Value = math.Log(v.Value) / math.Log(req.DataConvertConf.Value)
+				val := math.Log(v.Value) / math.Log(req.DataConvertConf.Value)
+				val, _ = decimal.NewFromFloat(val).Round(4).Float64()
+				newDataList[i].Value = val
 			}
 			//item.MaxData = math.Log(item.MaxData) / math.Log(v.ConvertValue)
 			//item.MinData = math.Log(item.MinData) / math.Log(v.ConvertValue)
@@ -874,9 +1093,10 @@ func AddChartInfo(req data_manage.AddChartInfoReq, source int, sysUser *system.A
 	chartInfo.UniqueCode = utils.MD5(utils.CHART_PREFIX + "_" + timestamp)
 	chartInfo.ChartType = 1 // 区间计算图
 	chartInfo.Calendar = "公历"
-	chartInfo.DateType = 6
+	chartInfo.DateType = req.DateType
 	chartInfo.StartDate = req.StartDate
 	chartInfo.EndDate = req.EndDate
+	chartInfo.StartYear = req.StartYear
 	chartInfo.SeasonStartDate = req.StartDate
 	chartInfo.SeasonEndDate = req.EndDate
 	chartInfo.LeftMin = req.LeftMin
@@ -1604,21 +1824,27 @@ func FormatChartEdbInfoMappings(chartInfoId int, mappings []*data_manage.ChartEd
 	return
 }*/
 
-func GetEdbDateByMoveForward(moveForward int, edbDataList []*data_manage.EdbDataList) (date string) {
-	moveForward = 0
+func GetEdbDateByMoveForward(startDate string, moveForward int, edbDataList []*data_manage.EdbDataList) (date string) {
 	// 根据日期进行排序
-	index := len(edbDataList) - 1 - moveForward
-	for k, v := range edbDataList {
-		if k == index {
+	index := 0
+	for _, v := range edbDataList {
+		if v.DataTime == startDate {
+			index += 1
+			continue
+		}
+		if index >= moveForward {
 			date = v.DataTime
-			return
+			break
+		}
+		if index > 0 {
+			index += 1
 		}
 	}
 	return
 }
 
 // HandleEdbDateChange 处理日期变换
-func HandleEdbDateChange(date string, dateChange []*data_manage.EdbDateConfDateChange) (newDate string, err error) {
+func HandleEdbDateChange(date string, dateChange []*data_manage.EdbDataDateChangeConf) (newDate string, err error) {
 	newDate = date
 	if newDate != "" {
 		if len(dateChange) > 0 {

+ 11 - 0
utils/common.go

@@ -865,6 +865,17 @@ func ConvertNumToCny(num float64) (str string, err error) {
 	return
 }
 
+// TimeFormatToYmd 时间格式转化 yyyy-MM-dd HH:mm:ss --> yyyy-MM-dd
+func TimeFormatToYmd(strTime string) string {
+	var Ymd string
+	var resultTime = StrTimeToTime(strTime)
+	year := resultTime.Year()
+	month := resultTime.Format("01")
+	day1 := resultTime.Day()
+	Ymd = strconv.Itoa(year) + "-" + month + "-" + strconv.Itoa(day1)
+	return Ymd
+}
+
 // GetNowWeekMonday 获取本周周一的时间
 func GetNowWeekMonday() time.Time {
 	offset := int(time.Monday - time.Now().Weekday())

+ 11 - 0
utils/constants.go

@@ -10,6 +10,7 @@ const (
 	FormatTimeHm               = "15:04"                   //时间格式
 	FormatDate                 = "2006-01-02"              //日期格式
 	FormatDateUnSpace          = "20060102"                //日期格式
+	ormatDateUnSpace           = "2006.01.02"              //日期格式
 	FormatDateTime             = "2006-01-02 15:04:05"     //完整时间格式
 	HlbFormatDateTime          = "2006-01-02_15:04:05.999" //完整时间格式
 	FormatDateTimeUnSpace      = "20060102150405"          //完整时间格式
@@ -176,6 +177,8 @@ const (
 	DATA_SOURCE_SCI_HQ                               = 88       // 卓创红期->88
 	DATA_SOURCE_OILCHEM                              = 89       // 隆众资讯 -> 89
 	DATA_SOURCE_CALCULATE_RANGEANLYSIS               = 87       //区间计算->87
+	DATA_SOURCE_PREDICT_CALCULATE_RANGEANLYSIS       = 90       // 预测指标区间计算->90
+	DATA_SOURCE_LY                                   = 91       // 粮油商务网
 )
 
 // 数据刷新频率
@@ -222,6 +225,7 @@ const (
 	CACHE_KEY_DAYNEW_REFRESH          = "admin:day_new:refresh"               //每日资讯拉取企业微信聊天记录
 	CACHE_KEY_DAYNEW_TRANSLATE        = "admin:day_new:translate"             //每日资讯中翻英
 	CACHE_KEY_ADMIN_OPERATE_RECORD    = "HZ_ADMIN_CACHE_ADMIN_OPERATE_RECORD" //系统用户操作日志队列
+	CACHE_KEY_EDBINFO_ADD             = "eta_api:edbinfo:add"                 //手工指标录入的key
 
 	CACHE_SYNC_ADMIN        = "hz_crm_eta:sync_admin"        // 同步用户的缓存队列key
 	CACHE_SYNC_ROLE         = "hz_crm_eta:sync_role"         // 同步角色的缓存队列key
@@ -327,6 +331,12 @@ const (
 	PREDICT_EDB_INFO_TYPE = 1 //指标类型 1:预测指标
 )
 
+// 是否关系 无实义
+const (
+	IS_YES = 1
+	IS_NO  = 0
+)
+
 // FrequencyDaysMap 频度日期的map关系
 var FrequencyDaysMap = map[string]int{
 	"天": 1, "周": 7, "月": 30, "季": 90, "年": 365,
@@ -421,6 +431,7 @@ var DataSourceEnMap = map[int]string{
 	DATA_SOURCE_BAIINFO:          "BAIINFO",
 	DATA_SOURCE_MYSTEEL_CHEMICAL: "Horizon Insights",
 	DATA_SOURCE_FUBAO:            "FuBao",
+	DATA_SOURCE_SCI_HQ:           "SCI(hongqi)",
 }
 
 const (