71 Commit-ok 5066dd3f8d ... 9b73a725b5

Szerző SHA1 Üzenet Dátum
  hsun 9b73a725b5 Merge branch 'master' into feature/eta_2.1.4 4 napja
  zwxi 110e82c92e Merge branch 'bugfix_5805' 5 napja
  zwxi 861f4f1b13 fix 5 napja
  zwxi cdfc8c12a4 Merge branch 'master' of http://8.136.199.33:3000/eta_server/eta_api 5 napja
  zwxi 2787308d36 Merge branch 'bugfix_5805' 5 napja
  zwxi 57c630849b fix 5 napja
  hsun 57b2b2e1f0 Merge branch 'master' of http://8.136.199.33:3000/eta_server/eta_api 5 napja
  hsun 8029e100d3 Merge branch 'feature/eta_2.0.3' 5 napja
  zwxi c0e0a5a432 Merge branch 'small_242' 5 napja
  Roc 888f0e95ac Merge branch 'bug/5723' 5 napja
  Roc 128f082a48 Merge remote-tracking branch 'origin/master' 5 napja
  Roc bda496346a Merge branch 'bug/5759' 5 napja
  zwxi c652700b8d fix 5 napja
  gmy 4fab7afd2f 路由修改 5 napja
  gmy 6c3ae865e8 Merge branch 'refs/heads/eta_2.0.8_ly_0804@guomengyuan' 5 napja
  gmy cda6c561b6 Merge branch 'master' of http://8.136.199.33:3000/eta_server/eta_api 5 napja
  gmy 57958cd02f 粮油商务网-路由修改 5 napja
  鲍自强 38739826ca Merge branch 'bzq1/eia_steo_custom' of eta_server/eta_api into master 5 napja
  鲍自强 e3cd26eb37 Merge branch 'bzq1/fix_login' of eta_server/eta_api into custom 5 napja
  鲍自强 75159a47ac Merge branch 'bzq1/fix_login' of eta_server/eta_api into master 5 napja
  鲍自强 2faaa7fef6 Merge branch 'bzq1/fix_pwd_bug' of eta_server/eta_api into custom 5 napja
  鲍自强 314d09876e Merge branch 'bzq1/fix_pwd_bug' of eta_server/eta_api into master 5 napja
  Roc 1fc322a220 Merge remote-tracking branch 'origin/custom' 5 napja
  Roc 463cd032d6 fix:移除空格 5 napja
  gmy 0e71229496 Merge branch 'refs/heads/eta_2.0.8_ly_0804@guomengyuan' 5 napja
  Roc 906799537a fix:移除空格 5 napja
  hsun 5efd85fb02 fix: 持仓分析指标刷新 5 napja
  hsun 2e2209bc0d fix: 期货公司名称 1 hete
  hsun 7c6eea2994 fix: 建仓过程 1 hete
  zqbao 1e40955282 fix:修改eiaSteo excel导出格式 1 hete
  zqbao fad4f68db4 fix:域用户检查响应ret 1 hete
  Roc 1cc1132612 Merge branch 'bug/5687' into custom 1 hete
  Roc 68e03eeeca Merge branch 'bug/5489' into custom 2 hete
  zwxi 0408c5c95c Merge branch 'bugfix_5753' into custom 2 hete
  zwxi da282e776f Merge branch 'custom' of http://8.136.199.33:3000/eta_server/eta_api into custom 2 hete
  Roc f34a2fa6df fix:手工数据导入模板2对于指标名称是空的做过滤,且不作为错误提示 2 hete
  xyxie b253de7bb2 Merge branch 'hotfix/edb_calculate_tbz' of eta_server/eta_api into custom 2 hete
  Roc b16921fbc5 fix:手工数据导入模板2对于空日期数据做过滤,且不作为错误提示 2 hete
  Roc 9cc515832c fix: 图表另存为后英文图表名称未获取bug修复,移动指标/图表时,更新es数据 2 hete
  zqbao e719a9e418 fix:修改用户密码正则 2 hete
  zwxi 513114e3da first 2 hete
  gmy 92182a4736 粮油商务网-指标库领取状态修改 2 hete
  gmy 737191c56e 粮油商务网-来源常量修改 2 hete
  gmy 5423f8b834 粮油商务网-来源常量修改 2 hete
  gmy d049f7059e 粮油商务网-来源常量修改 2 hete
  gmy 7f76efc15c 粮油商务网-导出列文案修改 2 hete
  gmy 9cb90a7f89 粮油商务网-最新数据展示调整 1 hónapja
  gmy 617bd6d364 粮油商务网-最新数据展示调整 1 hónapja
  gmy b7886afa13 粮油商务网-excel导出 1 hónapja
  gmy d67434d3c5 粮油商务网-excel导出 1 hónapja
  gmy 189e2253e2 粮油商务网-指标库删除-指标状态同步 1 hónapja
  gmy 90694fd689 粮油商务网-指标库删除-指标状态同步 1 hónapja
  gmy e462bc4269 粮油商务网-联调 1 hónapja
  gmy ee2446980b 粮油商务网-联调 1 hónapja
  gmy 3eed44f9d0 粮油商务网-联调 1 hónapja
  zqbao b228812193 fix:eiaSteo处理err 1 hónapja
  zqbao ac973f4083 fix:eiaSteo指标库id回显 1 hónapja
  gmy df8f5c970c 粮油商务网-联调 1 hónapja
  gmy bd19fde384 粮油商务网-联调 1 hónapja
  gmy 3f71f8d9ab 粮油商务网-联调 1 hónapja
  gmy 1b86e9b26e 粮油商务网-联调 1 hónapja
  gmy a2ab3f94e7 粮油商务网-日志包替换 1 hónapja
  gmy 6df4e7ac5d 粮油商务网-指标来源-91 1 hónapja
  gmy 8b341564a6 粮油商务网-参数名修改 1 hónapja
  gmy 7eea39a8e5 粮油商务网-swagger注释 1 hónapja
  gmy 0f7b360a14 粮油商务网-开发完毕 1 hónapja
  zqbao 05cd1be26d fix:eiaSteo数据列表 1 hónapja
  zqbao 366ce85d91 fix:去除eiasteo数据埋点 1 hónapja
  zqbao e07f9e2f4a fix:添加eiaSteo数据埋点 1 hónapja
  gmy 1b3eaa1be2 分类-指标列表-指标数据列表 1 hónapja
  zqbao 980f6ed22d add:添加eiaSteo的批量加入指标库,并修改目录层级 1 hónapja
33 módosított fájl, 2327 hozzáadás és 182 törlés
  1. 51 0
      controllers/data_manage/base_from_ly_classify_controller.go
  2. 525 0
      controllers/data_manage/base_from_ly_index_controller.go
  3. 4 2
      controllers/data_manage/chart_info.go
  4. 2 0
      controllers/data_manage/edb_info.go
  5. 614 11
      controllers/data_manage/eia_steo.go
  6. 1 0
      controllers/data_manage/future_good/future_good_chart_info.go
  7. 1 0
      controllers/data_manage/future_good/future_good_profit_chart_info.go
  8. 1 101
      controllers/data_manage/mysteel_chemical_data.go
  9. 7 2
      controllers/sys_admin.go
  10. 3 0
      controllers/trade_analysis/trade_analysis.go
  11. 51 18
      controllers/trade_analysis/warehouse.go
  12. 22 1
      controllers/user_login.go
  13. 36 16
      models/data_manage/base_from_eia_stero.go
  14. 48 0
      models/data_manage/base_from_ly_classify.go
  15. 108 0
      models/data_manage/base_from_ly_data.go
  16. 244 0
      models/data_manage/base_from_ly_index.go
  17. 2 0
      models/data_manage/edb_data_base.go
  18. 4 0
      models/data_manage/edb_info.go
  19. 99 0
      routers/commentsRouter.go
  20. 2 0
      routers/router.go
  21. 4 0
      services/data/base_edb_lib.go
  22. 79 0
      services/data/base_from_eia_steo.go
  23. 47 0
      services/data/base_from_ly_classify_service.go
  24. 249 0
      services/data/base_from_ly_index_service.go
  25. 20 0
      services/data/chart_info.go
  26. 1 0
      services/data/edb_info.go
  27. 2 0
      services/data/excel/custom_analysis_edb.go
  28. 20 15
      services/data/manual.go
  29. 7 5
      services/data/predict_edb_info.go
  30. 7 0
      services/data/trade_analysis/trade_analysis.go
  31. 31 11
      services/data/trade_analysis/trade_analysis_data.go
  32. 27 0
      utils/common.go
  33. 8 0
      utils/constants.go

+ 51 - 0
controllers/data_manage/base_from_ly_classify_controller.go

@@ -0,0 +1,51 @@
+// 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
+// @Title 包含分类下的指标名称
+// @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 = "获取成功"
+}

+ 525 - 0
controllers/data_manage/base_from_ly_index_controller.go

@@ -0,0 +1,525 @@
+// 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
+}
+
+var (
+	codeMax = 30 // 指标编码最大数量
+)
+
+// LyIndexList
+// @Title 获取指标列表
+// @Description 获取指标列表
+// @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 获取指标对应的数据列表
+// @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 新增加入到指标库校验
+// @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 指标添加到指标库
+// @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
+		}
+
+		// 试用平台更新用户累计新增指标数
+		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 导出指标数据
+// @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("指标名称/Metric Name")
+		rowFrequency := sheet.AddRow()
+		celFrequency := rowFrequency.AddCell()
+		celFrequency.SetValue("频度/Frequency")
+		rowUnit := sheet.AddRow()
+		celUnit := rowUnit.AddCell()
+		celUnit.SetValue("单位/Unit")
+		rowModifyDate := sheet.AddRow()
+		rowModifyCell := rowModifyDate.AddCell()
+		rowModifyCell.SetValue("更新时间/Update Time")
+
+		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"
+}

+ 4 - 2
controllers/data_manage/chart_info.go

@@ -873,6 +873,8 @@ func (this *ChartInfoController) ChartInfoMove() {
 			br.ErrMsg = "修改失败,Err:" + err.Error()
 			return
 		}
+		//添加es数据
+		go data.EsAddOrEditChartInfo(chartInfo.ChartInfoId)
 	}
 
 	if err != nil {
@@ -3105,6 +3107,7 @@ func (this *ChartInfoController) CopyChartInfo() {
 	chartInfo := &data_manage.ChartInfo{
 		ChartInfoId:     0,
 		ChartName:       req.ChartName,
+		ChartNameEn:     req.ChartName,
 		ChartClassifyId: req.ChartClassifyId,
 		SysUserId:       sysUser.AdminId,
 		SysUserRealName: sysUser.RealName,
@@ -4461,7 +4464,6 @@ func (this *ChartInfoController) PreviewSeasonChartInfo() {
 	br.Data = resp
 }
 
-
 // ChartInfoImgSetBySvg
 // @Title 图表图片上传
 // @Param   Img   query   string  true       "图片"
@@ -4519,4 +4521,4 @@ func (this *ChartInfoController) ChartInfoImgSetBySvg() {
 	br.Success = true
 	br.Data = resp
 	return
-}
+}

+ 2 - 0
controllers/data_manage/edb_info.go

@@ -3149,6 +3149,8 @@ func (this *EdbInfoController) EdbInfoMove() {
 			br.ErrMsg = "修改失败,Err:" + err.Error()
 			return
 		}
+		//添加es
+		data.AddOrEditEdbInfoToEs(req.EdbInfoId)
 	}
 
 	if err != nil {

+ 614 - 11
controllers/data_manage/eia_steo.go

@@ -1,14 +1,23 @@
 package data_manage
 
 import (
-	"github.com/rdlucklib/rdluck_tools/paging"
-	"github.com/tealeg/xlsx"
+	"encoding/json"
 	"eta/eta_api/models"
 	"eta/eta_api/models/data_manage"
+	"eta/eta_api/models/system"
+	"eta/eta_api/services/data"
+	"eta/eta_api/services/data_stat"
+	etaTrialService "eta/eta_api/services/eta_trial"
 	"eta/eta_api/utils"
+	"fmt"
 	"os"
 	"path/filepath"
+	"strconv"
+	"strings"
 	"time"
+
+	"github.com/rdlucklib/rdluck_tools/paging"
+	"github.com/tealeg/xlsx"
 )
 
 // EiaSteoClassify
@@ -35,16 +44,24 @@ func (this *EdbInfoController) EiaSteoClassify() {
 		br.ErrMsg = "获取分类失败,Err:" + err.Error()
 		return
 	}
+	childClassifyMap := make(map[int][]*data_manage.BaseFromEiaSteoClassifyView)
+	rootList := make([]*data_manage.BaseFromEiaSteoClassifyView, 0)
 	for _, v := range classifyList {
-		if v.ClassifyName == `` {
-			v.ClassifyName = v.ClassifyNameOriginal
+		if v.Level == 1 {
+			rootList = append(rootList, v)
+		} else {
+			childClassifyMap[v.ParentId] = append(childClassifyMap[v.ParentId], v)
+		}
+	}
+	for _, v := range rootList {
+		if existItems, ok := childClassifyMap[v.BaseFromEiaSteoClassifyId]; ok {
+			v.Child = existItems
 		}
 	}
-
 	br.Ret = 200
 	br.Success = true
 	br.Msg = "获取成功"
-	br.Data = classifyList
+	br.Data = rootList
 }
 
 // EiaSteoData
@@ -98,8 +115,18 @@ func (this *EdbInfoController) EiaSteoData() {
 	}
 	classifyId, _ := this.GetInt("BaseFromEiaSteoClassifyId")
 	if classifyId > 0 {
-		condition += ` AND base_from_eia_steo_classify_id = ? `
-		pars = append(pars, classifyId)
+		classifyList, err := data.GetClassifyALLById(classifyId)
+		if err != nil {
+			br.Msg = "获取数据失败"
+			br.ErrMsg = "获取分类数据失败,Err:" + err.Error()
+			return
+		}
+		var classifyIds []int
+		for _, v := range classifyList {
+			classifyIds = append(classifyIds, v.BaseFromEiaSteoClassifyId)
+		}
+		condition += ` AND base_from_eia_steo_classify_id IN (` + utils.GetOrmInReplace(len(classifyIds)) + `) `
+		pars = append(pars, classifyIds)
 	}
 
 	//获取指标
@@ -109,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 {
 
@@ -122,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),
@@ -133,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)
@@ -213,20 +260,25 @@ func EiaSteoDataExport(this *EdbInfoController, list []data_manage.EiaSteoIndexL
 	//获取指标数据
 	rowSecName := sheet.AddRow()
 	celSecName := rowSecName.AddCell()
-	celSecName.SetValue("指标名称")
+	celSecName.SetValue("指标名称/Metric Name")
+	frequency := sheet.AddRow()
+	freqCell := frequency.AddCell()
+	freqCell.SetValue("频度/Frequency")
 	rowUnit := sheet.AddRow()
 	celUnit := rowUnit.AddCell()
-	celUnit.SetValue("单位")
+	celUnit.SetValue("单位/Unit")
 
 	rowModifyDate := sheet.AddRow()
 	rowModifyCell := rowModifyDate.AddCell()
-	rowModifyCell.SetValue("更新时间")
+	rowModifyCell.SetValue("更新时间/Update Time")
 
 	dataMap := make(map[string]map[string]*data_manage.BaseFromEiaSteoDataItem)
 	var indexCodeList []string
 	for _, v := range list {
 		cellSenName := rowSecName.AddCell()
 		cellSenName.SetValue(v.IndexName)
+		freqCell := frequency.AddCell()
+		freqCell.SetValue(v.Frequency)
 		celUnit := rowUnit.AddCell()
 		celUnit.SetValue(v.Unit)
 		rowModifyCell := rowModifyDate.AddCell()
@@ -289,3 +341,554 @@ func EiaSteoDataExport(this *EdbInfoController, list []data_manage.EiaSteoIndexL
 	br.Success = true
 	br.Msg = "success"
 }
+
+// EiaSteoBatchSearch
+// @Title EiaSteo批量操作查询接口
+// @Description EiaSteo批量操作查询接口
+// @Param   BaseFromEiaSteoClassifyIds   query   string  true       "分类id"
+// @Param   Keyword   query   string  true       "名称关键词"
+// @Success 200 {object} data_manage.LzFrequency
+// @router /eia_steo/batch_search [get]
+func (this *EdbInfoController) EiaSteoBatchSearch() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	classifyIdStr := this.GetString("BaseFromEiaSteoClassifyIds")
+
+	var condition string
+	var pars []interface{}
+	classifyIds := strings.Split(classifyIdStr, ",")
+	if len(classifyIds) > 0 && classifyIds[0] != `` {
+		condition += " AND base_from_eia_steo_classify_id IN (" + utils.GetOrmInReplace(len(classifyIds)) + " ) "
+		pars = append(pars, classifyIds)
+	}
+	keyword := this.GetString("Keyword")
+	if keyword != `` {
+		condition += " AND (index_name like ? OR index_code like ?) "
+		pars = utils.GetLikeKeywordPars(pars, keyword, 2)
+	}
+
+	if classifyIdStr == `` && keyword == `` {
+		var list = make([]*data_manage.BaseFromEiaSteoIndex, 0)
+		br.Ret = 200
+		br.Success = true
+		br.Msg = "获取成功"
+		br.Data = list
+		return
+	}
+
+	list, err := data_manage.GetEiaSteoIndexList(condition, pars)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = list
+}
+
+// AddCheck
+// @Title 新增校验
+// @Description 新增校验
+// @Param	request	body request.BusinessDataBatchAddCheckReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /eia_steo/edb_info/add_check [post]
+func (c *EdbInfoController) EiaSteoAddCheck() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	sysUser := c.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	var req data_manage.EiaSteoDataBatchAddCheckReq
+	if e := json.Unmarshal(c.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + e.Error()
+		return
+	}
+	codeMax := 30
+	codeLen := len(req.IndexCodes)
+	if codeLen == 0 {
+		br.Msg = "请选择指标"
+		return
+	}
+	if codeLen > codeMax {
+		br.Msg = fmt.Sprintf("最多只能选择%d个指标", codeMax)
+		return
+	}
+
+	// 获取指标库已有指标
+	existsEdb, e := data_manage.GetEdbCodesBySource(utils.DATA_SOURCE_EIA_STEO)
+	if e != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取自有数据已添加的指标失败, Err: " + e.Error()
+		return
+	}
+	existMap := make(map[string]*data_manage.EdbInfo)
+	for _, v := range existsEdb {
+		existMap[v.EdbCode] = v
+	}
+
+	// 查询选中的指标
+	cond := fmt.Sprintf(` AND index_code IN (%s) `, utils.GetOrmInReplace(len(req.IndexCodes)))
+	pars := make([]interface{}, 0)
+	pars = append(pars, req.IndexCodes)
+	list, err := data_manage.GetEiaSteoIndexList(cond, pars)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取eiaSteo原始指标列表失败, Err: " + err.Error()
+		return
+	}
+
+	resp := make([]*data_manage.BaseFromEiaSteoIndexItem, 0)
+	for _, v := range list {
+		if edbInfo, ok := existMap[v.IndexCode]; ok {
+			resp = append(resp, &data_manage.BaseFromEiaSteoIndexItem{
+				BaseFromEiaSteoIndexId:    v.BaseFromEiaSteoIndexId,
+				BaseFromEiaSteoClassifyId: v.BaseFromEiaSteoClassifyId,
+				IndexCode:                 v.IndexCode,
+				IndexName:                 v.IndexName,
+				EdbInfoId:                 edbInfo.EdbInfoId,
+				EdbUniqueCode:             edbInfo.UniqueCode,
+				EdbClassifyId:             edbInfo.ClassifyId,
+				EdbExist:                  1,
+			})
+		} else {
+			resp = append(resp, &data_manage.BaseFromEiaSteoIndexItem{
+				BaseFromEiaSteoIndexId:    v.BaseFromEiaSteoIndexId,
+				BaseFromEiaSteoClassifyId: v.BaseFromEiaSteoClassifyId,
+				IndexCode:                 v.IndexCode,
+				IndexName:                 v.IndexName,
+				EdbInfoId:                 0,
+				EdbUniqueCode:             "",
+				EdbClassifyId:             0,
+				EdbExist:                  0,
+			})
+		}
+	}
+	br.Data = resp
+	br.Msg = "校验成功"
+	br.Ret = 200
+	br.Success = true
+}
+
+// EiaSteoNameCheck
+// @Title 重名校验
+// @Description 批量新增
+// @Param	request	body data_manage.AddEdbInfoReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /eia_steo/name_check [post]
+func (c *EdbInfoController) EiaSteoNameCheck() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	sysUser := c.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	var req []*data_manage.NameCheckEdbInfoReq
+	if e := json.Unmarshal(c.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + e.Error()
+		return
+	}
+	if len(req) == 0 {
+		br.Msg = "请选择指标"
+		return
+	}
+	codeMax := 30
+	codeLen := len(req)
+	if codeLen > codeMax {
+		br.Msg = fmt.Sprintf("最多只能选择%d个指标", codeMax)
+		return
+	}
+
+	type NameCheckResult struct {
+		EdbCode string
+		EdbName string
+		Exist   bool
+	}
+	indexNames := make([]string, 0)
+	resp := make([]*NameCheckResult, 0)
+	for _, v := range req {
+		v.EdbCode = strings.TrimSpace(v.EdbCode)
+		if v.EdbCode == "" {
+			br.Msg = "指标ID不可为空"
+			return
+		}
+		v.EdbName = strings.TrimSpace(v.EdbName)
+		if v.EdbName == "" {
+			br.Msg = "请输入指标名称"
+			return
+		}
+		indexNames = append(indexNames, v.EdbName)
+		resp = append(resp, &NameCheckResult{
+			EdbCode: v.EdbCode,
+			EdbName: v.EdbName,
+		})
+		dataItems, err := data_manage.GetEdbDataAllByEdbCode(v.EdbCode, utils.DATA_SOURCE_EIA_STEO, 0, utils.EDB_DATA_LIMIT)
+		if err != nil && err.Error() != utils.ErrNoRow() {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取钢联已存在信息失败,Err:" + err.Error()
+			return
+		}
+		if len(dataItems) <= 0 {
+			respItem, err := data.AddEdbData(utils.DATA_SOURCE_EIA_STEO, v.EdbCode, v.Frequency)
+			if err != nil {
+				br.Msg = "获取失败"
+				br.ErrMsg = "获取失败,Err:" + err.Error()
+				return
+			}
+			if respItem.Ret != 200 {
+				br.Msg = "未搜索到该指标"
+				br.ErrMsg = respItem.ErrMsg + ";EdbCode:" + v.EdbCode
+				return
+			}
+		}
+	}
+
+	// 重名校验
+	edbList, e := data_manage.GetEdbInfoByNameArr(indexNames, utils.EDB_INFO_TYPE)
+	if e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "获取重名指标失败, Err: " + e.Error()
+		return
+	}
+	nameExists := make(map[string]bool)
+	for _, v := range edbList {
+		nameExists[v.EdbName] = true
+	}
+	if len(nameExists) > 0 {
+		for _, v := range resp {
+			v.Exist = nameExists[v.EdbName]
+		}
+	}
+
+	br.Data = resp
+	br.Msg = "校验成功"
+	br.Ret = 200
+	br.Success = true
+}
+
+// EiaSteoBatchAdd
+// @Title eiaSteo批量新增
+// @Description eiaSteo批量新增
+// @Param	request	body data_manage.AddEdbInfoReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /eia_steo/batch_add [post]
+func (this *EdbInfoController) EiaSteoBatchAdd() {
+	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_EIA_STEO_" + strconv.Itoa(sysUser.AdminId)
+	defer func() {
+		if deleteCache {
+			_ = utils.Rc.Delete(cacheKey)
+		}
+	}()
+	if !utils.Rc.SetNX(cacheKey, 1, 30*time.Second) {
+		deleteCache = false
+		br.Msg = "系统处理中,请稍后重试!"
+		br.ErrMsg = "系统处理中,请稍后重试!" + sysUser.RealName + ";data:" + string(this.Ctx.Input.RequestBody)
+		return
+	}
+	var req []*data_manage.AddEdbInfoReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + e.Error()
+		return
+	}
+	if len(req) == 0 {
+		br.Msg = "请选择指标"
+		return
+	}
+	if len(req) > 30 {
+		br.Msg = "批量添加指标数量不得超过30个"
+		return
+	}
+	for _, v := range req {
+		v.EdbCode = strings.TrimSpace(v.EdbCode)
+		if v.EdbCode == "" {
+			br.Msg = "指标ID不可为空"
+			return
+		}
+		v.EdbName = strings.TrimSpace(v.EdbName)
+		if v.EdbName == "" {
+			br.Msg = "请输入指标名称"
+			return
+		}
+		v.Frequency = strings.TrimSpace(v.Frequency)
+		if v.Frequency == "" {
+			br.Msg = "请选择频度"
+			return
+		}
+		v.Unit = strings.TrimSpace(v.Unit)
+		if v.Unit == "" {
+			br.Msg = "请输入单位"
+			return
+		}
+		if v.ClassifyId <= 0 {
+			br.Msg = "请选择分类"
+			return
+		}
+	}
+
+	// 限定同一时间最多批量新增30个指标
+	for _, v := range req {
+		var r data.EiaSteoIndexSource2EdbReq
+		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.EiaSteoIndexSource2Edb(r, this.Lang)
+		if e != nil {
+			br.Msg = "操作失败"
+			if errMsg != "" {
+				br.Msg = errMsg
+			}
+			br.ErrMsg = e.Error()
+			return
+		}
+		if skip {
+			continue
+		}
+
+		// 试用平台更新用户累计新增指标数
+		if utils.BusinessCode == utils.BusinessCodeSandbox {
+			go func() {
+				adminItem, e := system.GetSysAdminById(sysUser.AdminId)
+				if e != nil {
+					tips := fmt.Sprintf("试用平台更新用户累计新增指标数-获取用户失败, Err: " + e.Error())
+					utils.FileLog.Info(tips)
+					return
+				}
+				if adminItem.DepartmentName != "ETA试用客户" {
+					return
+				}
+				var ur etaTrialService.EtaTrialUserReq
+				ur.Mobile = adminItem.Mobile
+				_, _ = etaTrialService.UpdateUserIndexNum(ur)
+			}()
+		}
+
+		// 新增操作日志
+		{
+			edbLog := new(data_manage.EdbInfoLog)
+			edbLog.EdbInfoId = edbInfo.EdbInfoId
+			edbLog.SourceName = edbInfo.SourceName
+			edbLog.Source = edbInfo.Source
+			edbLog.EdbCode = edbInfo.EdbCode
+			edbLog.EdbName = edbInfo.EdbName
+			edbLog.ClassifyId = edbInfo.ClassifyId
+			edbLog.SysUserId = sysUser.AdminId
+			edbLog.SysUserRealName = sysUser.RealName
+			edbLog.CreateTime = time.Now()
+			edbLog.Content = string(this.Ctx.Input.RequestBody)
+			edbLog.Status = "新增指标"
+			edbLog.Method = this.Ctx.Input.URI()
+			go data_manage.AddEdbInfoLog(edbLog)
+		}
+	}
+
+	br.Msg = "操作成功"
+	br.Ret = 200
+	br.Success = true
+	br.IsAddLog = true
+}
+
+// EiaSteoAdd
+// @Title 新增eiaSteo指标接口
+// @Description 新增eiaSteo指标接口
+// @Param	request	body data_manage.AddEdbInfoReq true "type json string"
+// @Success Ret=200 保存成功
+// @router /eia_steo/edb_info/add [post]
+func (this *EdbInfoController) EiaSteoAdd() {
+	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
+	}
+	deleteCache := true
+	cacheKey := "CACHE_EDB_INFO_ADD_" + 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
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	req.EdbName = strings.Trim(req.EdbName, " ")
+	req.EdbCode = strings.Trim(req.EdbCode, " ")
+
+	if req.EdbCode == "" {
+		br.Msg = "指标ID不能为空"
+		return
+	}
+
+	if req.EdbName == "" {
+		br.Msg = "指标名称不能为空"
+		return
+	}
+
+	if req.Frequency == "" {
+		br.Msg = "频率不能为空"
+		return
+	}
+
+	if req.Unit == "" {
+		br.Msg = "单位不能为空"
+		return
+	}
+
+	if req.ClassifyId <= 0 {
+		br.Msg = "请选择分类"
+		return
+	}
+
+	tmpInfo, err := data_manage.GetBaseFromEiaSteoIndexByCode(req.EdbCode)
+	if err != nil {
+		if err.Error() != utils.ErrNoRow() {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取失败,Err:" + err.Error()
+			return
+		}
+	}
+	var source int
+	if tmpInfo != nil {
+		source = utils.DATA_SOURCE_EIA_STEO
+	} else {
+		br.Msg = "指标不存在"
+		return
+	}
+
+	// 指标入库
+	edbInfo, err, errMsg, isSendEmail := data.EdbInfoAdd(source, utils.DATA_SUB_SOURCE_EDB, req.ClassifyId, req.EdbCode, req.EdbName, req.Frequency, req.Unit, req.StartDate, req.EndDate, sysUser.AdminId, sysUser.RealName, this.Lang)
+	if err != nil {
+		br.Msg = "保存失败"
+		if errMsg != `` {
+			br.Msg = errMsg
+		}
+		br.ErrMsg = err.Error()
+		br.IsSendEmail = isSendEmail
+		return
+	}
+
+	// 试用平台更新用户累计新增指标数
+	adminItem, e := system.GetSysAdminById(sysUser.AdminId)
+	if e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "获取系统用户数据失败,Err:" + e.Error()
+		return
+	}
+	if utils.BusinessCode == utils.BusinessCodeSandbox && adminItem.DepartmentName == "ETA试用客户" {
+		go func() {
+			var r etaTrialService.EtaTrialUserReq
+			r.Mobile = adminItem.Mobile
+			_, _ = etaTrialService.UpdateUserIndexNum(r)
+		}()
+	}
+
+	//新增操作日志
+	{
+		// 添加钢联指标更新日志
+		if edbInfo.Source == utils.DATA_SOURCE_MYSTEEL_CHEMICAL {
+			go data_stat.AddEdbInfoUpdateLog(edbInfo.EdbInfoId, 1, "", sysUser, 2)
+		}
+
+		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)
+	}
+
+	// 更新es
+	go data.AddOrEditEdbInfoToEs(edbInfo.EdbInfoId)
+
+	resp := new(data_manage.AddEdbInfoResp)
+	resp.EdbInfoId = edbInfo.EdbInfoId
+	resp.UniqueCode = edbInfo.UniqueCode
+	resp.ClassifyId = edbInfo.ClassifyId
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "保存成功"
+	br.Data = resp
+	br.IsAddLog = true
+}

+ 1 - 0
controllers/data_manage/future_good/future_good_chart_info.go

@@ -2862,6 +2862,7 @@ func copyChartInfo(oldChartInfo *data_manage.ChartInfo, chartClassifyId int, cha
 	chartInfo = &data_manage.ChartInfo{
 		ChartInfoId:     0,
 		ChartName:       chartName,
+		ChartNameEn:     chartName,
 		ChartClassifyId: chartClassifyId,
 		SysUserId:       sysUser.AdminId,
 		SysUserRealName: sysUser.RealName,

+ 1 - 0
controllers/data_manage/future_good/future_good_profit_chart_info.go

@@ -771,6 +771,7 @@ func copyProfitChartInfo(oldChartInfo *data_manage.ChartInfo, chartClassifyId in
 	chartInfo = &data_manage.ChartInfo{
 		ChartInfoId:     0,
 		ChartName:       chartName,
+		ChartNameEn:     chartName,
 		ChartClassifyId: chartClassifyId,
 		SysUserId:       sysUser.AdminId,
 		SysUserRealName: sysUser.RealName,

+ 1 - 101
controllers/data_manage/mysteel_chemical_data.go

@@ -1630,7 +1630,7 @@ func (this *EdbInfoController) Add() {
 	adminItem, e := system.GetSysAdminById(sysUser.AdminId)
 	if e != nil {
 		br.Msg = "操作失败"
-		br.ErrMsg = "获取系统用户数据失败,Err:" + err.Error()
+		br.ErrMsg = "获取系统用户数据失败,Err:" + e.Error()
 		return
 	}
 	if utils.BusinessCode == utils.BusinessCodeSandbox && adminItem.DepartmentName == "ETA试用客户" {
@@ -1678,106 +1678,6 @@ func (this *EdbInfoController) Add() {
 }
 
 // AddCheck
-// @Title 新增指标检测接口
-// @Description 新增指标检测接口
-// @Param   EdbCode   query   string  true      "指标编码/指标代码"
-// @Success Ret=200 保存成功
-// @router /mysteel_chemical/edb_info/add_check [get]
-// func (this *EdbInfoController) AddCheck() {
-// 	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.AddCheckEdbInfoReq
-// 	if err := json.Unmarshal(this.Ctx.Input.RequestBody, &req); err != nil {
-// 		br.Msg = "参数解析异常!"
-// 		br.ErrMsg = "参数解析失败,Err:" + err.Error()
-// 		return
-// 	}
-
-// 	source := utils.DATA_SOURCE_MYSTEEL_CHEMICAL
-// 	indexNameMap := make(map[string]string)
-// 	indexNames := make([]string, 0)
-// 	for _, v := range req {
-// 		v.EdbCode = strings.Trim(v.EdbCode, "\t")
-// 		v.EdbCode = strings.Trim(v.EdbCode, " ")
-// 		v.EdbCode = strings.Replace(v.EdbCode, "\t", "", -1)
-// 		if v.EdbCode == "" {
-// 			br.Msg = "请输入指标ID"
-// 			return
-// 		}
-// 		v.EdbName = strings.Trim(v.EdbName, "\t")
-// 		v.EdbName = strings.Trim(v.EdbName, " ")
-// 		v.EdbName = strings.Replace(v.EdbName, "\t", "", -1)
-// 		if v.EdbName == "" {
-// 			br.Msg = "请输入指标名称"
-// 			return
-// 		}
-// 		indexNames = append(indexNames, v.EdbName)
-
-// 		item, err := data_manage.GetEdbInfoByEdbCode(source, edbCode)
-// 		if err != nil && err.Error() != utils.ErrNoRow() {
-// 			br.Msg = "获取失败"
-// 			br.ErrMsg = "获取失败,Err:" + err.Error()
-// 			return
-// 		}
-
-// 		resp := new(data_manage.EdbInfoMySteelChemicalCheckResp)
-// 		if item != nil && item.EdbInfoId > 0 {
-// 			resp.Status = 1
-// 			// 查询该指标是否有权限
-// 			obj := data_manage.EdbInfoNoPermissionAdmin{}
-// 			conf, err := obj.GetByEdbInfoIdAndAdminId(this.SysUser.AdminId, item.EdbInfoId)
-// 			if err != nil && err.Error() != utils.ErrNoRow() {
-// 				br.Msg = "获取失败"
-// 				br.ErrMsg = "获取当前账号的不可见指标配置失败,err:" + err.Error()
-// 				return
-// 			}
-// 			if conf != nil {
-// 				resp.Status = 3
-// 			}
-// 		} else {
-// 			resp.Status = 2
-// 			dataItems, err := data_manage.GetEdbDataAllByEdbCode(edbCode, source, 0, utils.EDB_DATA_LIMIT)
-// 			if err != nil && err.Error() != utils.ErrNoRow() {
-// 				br.Msg = "获取失败"
-// 				br.ErrMsg = "获取钢联已存在信息失败,Err:" + err.Error()
-// 				return
-// 			}
-
-// 			if len(dataItems) <= 0 {
-// 				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
-// 				}
-// 			}
-// 		}
-// 	}
-
-// 	br.Ret = 200
-// 	br.Success = true
-// 	br.Msg = "保存成功"
-// 	br.Data = resp
-// 	br.IsAddLog = true
-// }
-
-// AddCheck
 // @Title 新增校验
 // @Description 新增校验
 // @Param	request	body request.BusinessDataBatchAddCheckReq true "type json string"

+ 7 - 2
controllers/sys_admin.go

@@ -12,10 +12,11 @@ import (
 	etaTrialService "eta/eta_api/services/eta_trial"
 	"eta/eta_api/utils"
 	"fmt"
-	"github.com/rdlucklib/rdluck_tools/paging"
 	"strconv"
 	"strings"
 	"time"
+
+	"github.com/rdlucklib/rdluck_tools/paging"
 )
 
 // 系统用户
@@ -459,7 +460,7 @@ func (this *SysAdminController) Add() {
 			br.Msg = "请输入密码"
 			return
 		}
-		if !utils.CheckPwd(originPass) {
+		if !utils.CheckPwdV2(originPass) {
 			br.Msg = "密码格式错误,请重新输入"
 			return
 		}
@@ -1251,6 +1252,10 @@ func (this *SysAdminController) ResetPass() {
 	}
 	pwd := string(b)
 	//pwd = strings.ToLower(pwd)
+	if !utils.CheckPwdV2(pwd) {
+		br.Msg = "密码格式错误,请重新输入"
+		return
+	}
 	pwd = utils.MD5(pwd)
 
 	adminInfo.Password = pwd

+ 3 - 0
controllers/trade_analysis/trade_analysis.go

@@ -227,6 +227,9 @@ func (this *TradeAnalysisController) GetTradeClassifyList() {
 		// 郑商所
 		if v.Exchange == tradeAnalysisModel.TradeExchangeZhengzhou {
 			name := trade_analysis.GetZhengzhouClassifyName(v.ClassifyName)
+			if name == "" {
+				continue
+			}
 			if classifyExist[name] {
 				continue
 			}

+ 51 - 18
controllers/trade_analysis/warehouse.go

@@ -8,6 +8,7 @@ import (
 	tradeAnalysisModel "eta/eta_api/models/data_manage/trade_analysis"
 	tradeAnalysisRequest "eta/eta_api/models/data_manage/trade_analysis/request"
 	tradeAnalysisResponse "eta/eta_api/models/data_manage/trade_analysis/response"
+	"eta/eta_api/services/alarm_msg"
 	"eta/eta_api/services/data"
 	tradeAnalysisService "eta/eta_api/services/data/trade_analysis"
 	"eta/eta_api/utils"
@@ -904,6 +905,17 @@ func (this *WarehouseController) List() {
 			br.ErrMsg = "获取信息失败,GetChartClassify,Err:" + err.Error()
 			return
 		}
+		if classifyIds == "" {
+			resp := new(data_manage.ChartListResp)
+			page = paging.GetPaging(currentIndex, pageSize, 0)
+			resp.Paging = page
+			resp.List = make([]*data_manage.ChartInfoView, 0)
+			br.Ret = 200
+			br.Success = true
+			br.Msg = "获取成功"
+			br.Data = resp
+			return
+		}
 		condition += " AND chart_classify_id IN(" + classifyIds + ") "
 	}
 	if keyword != "" {
@@ -1643,6 +1655,7 @@ func (this *WarehouseController) EdbSave() {
 	// 根据EdbInfoId判断是否需要更新指标
 	var newEdbIds []int
 	edbUpdateCols := []string{"CalculateFormula", "ModifyTime"}
+	newEdbRefresh := make([]*data_manage.EdbInfo, 0)
 	for _, v := range req.EdbInfoList {
 		// 图表配置-即指标计算公式
 		conf := extraConfig
@@ -1681,6 +1694,25 @@ func (this *WarehouseController) EdbSave() {
 				continue
 			}
 			edbInfo = edb
+
+			// 刷新指标数据
+			res, e := data.RefreshEdbData(edbInfo.EdbInfoId, edbInfo.Source, edbInfo.SubSource, edbInfo.EdbCode, utils.BASE_START_DATE)
+			if e != nil {
+				resp.Fail = append(resp.Fail, &tradeAnalysisModel.WarehouseEdbSaveRespItem{
+					WarehouseEdbSaveItem: *v,
+					Tips:                 "刷新失败",
+					ErrMsg:               fmt.Sprintf("刷新失败, %v", e),
+				})
+				continue
+			}
+			if res.Ret != 200 {
+				resp.Fail = append(resp.Fail, &tradeAnalysisModel.WarehouseEdbSaveRespItem{
+					WarehouseEdbSaveItem: *v,
+					Tips:                 "刷新失败",
+					ErrMsg:               fmt.Sprintf("刷新失败, Ret: %d, err: %v", res.Ret, e),
+				})
+				continue
+			}
 		}
 
 		// 新增指标
@@ -1713,25 +1745,9 @@ func (this *WarehouseController) EdbSave() {
 			}
 			newEdbIds = append(newEdbIds, edb.EdbInfoId)
 			edbInfo = edb
-		}
 
-		// 刷新指标数据
-		res, e := data.RefreshEdbData(edbInfo.EdbInfoId, edbInfo.Source, edbInfo.SubSource, edbInfo.EdbCode, utils.BASE_START_DATE)
-		if e != nil {
-			resp.Fail = append(resp.Fail, &tradeAnalysisModel.WarehouseEdbSaveRespItem{
-				WarehouseEdbSaveItem: *v,
-				Tips:                 "刷新失败",
-				ErrMsg:               fmt.Sprintf("刷新失败, %v", e),
-			})
-			continue
-		}
-		if res.Ret != 200 {
-			resp.Fail = append(resp.Fail, &tradeAnalysisModel.WarehouseEdbSaveRespItem{
-				WarehouseEdbSaveItem: *v,
-				Tips:                 "刷新失败",
-				ErrMsg:               fmt.Sprintf("刷新失败, Ret: %d, err: %v", res.Ret, e),
-			})
-			continue
+			// 新增指标的刷新走异步吧, 指标如果没数据, 用户自己删了就行
+			newEdbRefresh = append(newEdbRefresh, edbInfo)
 		}
 
 		v.EdbInfoId = edbInfo.EdbInfoId
@@ -1771,6 +1787,23 @@ func (this *WarehouseController) EdbSave() {
 		}
 	}
 
+	// 异步刷新新增指标
+	if len(newEdbRefresh) > 0 {
+		go func() {
+			var refreshTips string
+			for _, edb := range newEdbRefresh {
+				_, e = data.RefreshEdbData(edb.EdbInfoId, edb.Source, edb.SubSource, edb.EdbCode, utils.BASE_START_DATE)
+				if e != nil {
+					refreshTips += fmt.Sprintf("刷新指标失败: %s, err: %v\n", edb.EdbCode, e)
+				}
+			}
+			if refreshTips != "" {
+				utils.FileLog.Info(refreshTips)
+				alarm_msg.SendAlarmMsg(refreshTips, 2)
+			}
+		}()
+	}
+
 	br.Data = resp
 	br.Ret = 200
 	br.Success = true

+ 22 - 1
controllers/user_login.go

@@ -10,10 +10,11 @@ import (
 	"eta/eta_api/services/eta_trial"
 	"eta/eta_api/utils"
 	"fmt"
-	"github.com/mojocn/base64Captcha"
 	"image/color"
 	"strings"
 	"time"
+
+	"github.com/mojocn/base64Captcha"
 )
 
 // UserLoginController 登录-无需Token
@@ -973,6 +974,7 @@ func (this *UserLoginController) CheckUserLdap() {
 	if e != nil {
 		// 无该用户视作普通用户
 		if e.Error() == utils.ErrNoRow() {
+			br.Ret = 200
 			br.Data = false
 			br.Success = true
 			br.Msg = "操作成功"
@@ -1042,12 +1044,29 @@ func (this *UserLoginController) BaseInfo() {
 		return
 	}
 
+	logoCnMini, e := models.GetBusinessConfByKey("LogoCNMini")
+	if e != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取商家配置失败, Err: " + e.Error()
+		return
+	}
+
+	logoEnMini, e := models.GetBusinessConfByKey("LogoENMini")
+	if e != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取商家配置失败, Err: " + e.Error()
+		return
+	}
+
+
 	type BaseInfoResp struct {
 		Icp      *models.BusinessConf `description:"Icp信息"`
 		ETATitle *models.BusinessConf `description:"eta系统名称"`
 		TabName  *models.BusinessConf `description:"tab页名称"`
 		LogoCn   *models.BusinessConf `description:"中文logo"`
 		LogoEn   *models.BusinessConf `description:"英文logo"`
+		LogoCnMini   *models.BusinessConf `description:"中文logoMini"`
+		LogoEnMini   *models.BusinessConf `description:"英文logoMini"`
 	}
 
 	resp := BaseInfoResp{
@@ -1056,6 +1075,8 @@ func (this *UserLoginController) BaseInfo() {
 		TabName:  tabName,
 		LogoCn:   logoCn,
 		LogoEn:   logoEn,
+		LogoCnMini:   logoCnMini,
+		LogoEnMini:   logoEnMini,
 	}
 
 	br.Data = resp

+ 36 - 16
models/data_manage/base_from_eia_stero.go

@@ -2,9 +2,10 @@ package data_manage
 
 import (
 	"eta/eta_api/utils"
+	"time"
+
 	"github.com/beego/beego/v2/client/orm"
 	"github.com/rdlucklib/rdluck_tools/paging"
-	"time"
 )
 
 // BaseFromEiaSteoIndex EiaSteo指标
@@ -33,20 +34,11 @@ type BaseFromEiaSteoIndexItem struct {
 	BaseFromEiaSteoIndexId    int    `orm:"column(base_from_eia_steo_index_id);pk"`
 	BaseFromEiaSteoClassifyId int    `description:"指标分类id"`
 	IndexCode                 string `description:"指标编码"`
-	IndexName                 string `description:"指标名称(中文名称)"`
-	IndexNameOriginal         string `description:"指标名称(原始名称)"`
-	Frequency                 string `description:"频度"`
-	Level                     int    `description:"指标层级(原始层级)"`
-	Unit                      string `description:"单位"`
-	Super                     string `description:"我也不知道是个啥,反正先存起来,万一用到了呢"`
-	Precision                 int    `description:"精度,我也不知道会不会用到,反正先存起来,万一用到了呢"`
-	LastHistorical            string `description:"最近的历史记录,我也不知道会不会用到,反正先存起来,万一用到了呢"`
-	Description               string `description:"备注信息,我也不知道会不会用到,反正先存起来,万一用到了呢"`
-	IsMappable                int    `description:"是否可映射,我也不知道会不会用到,反正先存起来,万一用到了呢"`
-	StartDate                 string `description:"开始日期"`
-	EndDate                   string `description:"结束日期"`
-	ModifyTime                string `description:"最新更新时间"`
-	CreateTime                string `description:"创建时间"`
+	IndexName                 string `description:"指标名称"`
+	EdbInfoId                 int    `description:"eta指标库的id"`
+	EdbUniqueCode             string `description:"指标库唯一编码"`
+	EdbClassifyId             int    `description:"指标库分类ID"`
+	EdbExist                  int    `description:"指标库是否已添加:0-否;1-是"`
 }
 
 // BaseFromEiaSteoClassify EiaSteo分类
@@ -54,10 +46,21 @@ type BaseFromEiaSteoClassify struct {
 	BaseFromEiaSteoClassifyId int       `orm:"column(base_from_eia_steo_classify_id);pk"`
 	ClassifyName              string    `description:"分类名称(中文名称)"`
 	ClassifyNameOriginal      string    `description:"分类名称(原始名称)"`
+	ParentId                  int       `description:"父级id"`
+	Level                     int       `description:"层级"`
 	ModifyTime                time.Time `description:"最新更新时间"`
 	CreateTime                time.Time `description:"创建时间"`
 }
 
+type BaseFromEiaSteoClassifyView struct {
+	BaseFromEiaSteoClassifyId int                            `orm:"column(base_from_eia_steo_classify_id);pk"`
+	ClassifyName              string                         `description:"分类名称(中文名称)"`
+	ClassifyNameOriginal      string                         `description:"分类名称(原始名称)"`
+	ParentId                  int                            `description:"父级id"`
+	Level                     int                            `description:"层级"`
+	Child                     []*BaseFromEiaSteoClassifyView `description:"子级分类列表"`
+}
+
 // BaseFromEiaSteoData EiaSteo数据表
 type BaseFromEiaSteoData struct {
 	BaseFromEiaSteoDataId  int       `orm:"column(base_from_eia_steo_data_id);pk"`
@@ -81,18 +84,35 @@ type BaseFromEiaSteoDataItem struct {
 }
 
 // GetEiaSteoClassifyList 获取分类列表
-func GetEiaSteoClassifyList() (items []*BaseFromEiaSteoClassify, err error) {
+func GetEiaSteoClassifyList() (items []*BaseFromEiaSteoClassifyView, err error) {
 	sql := ` SELECT * FROM base_from_eia_steo_classify  ORDER BY base_from_eia_steo_classify_id ASC `
 	o := orm.NewOrmUsingDB("data")
 	o.Raw(sql).QueryRows(&items)
 	return
 }
 
+// GetEiaSteoClassifyById 根据分类id获取分类
+func GetEiaSteoClassifyById(classifyId int) (item *BaseFromEiaSteoClassify, err error) {
+	sql := ` SELECT * FROM base_from_eia_steo_classify WHERE base_from_eia_steo_classify_id=? `
+	o := orm.NewOrmUsingDB("data")
+	err = o.Raw(sql, classifyId).QueryRow(&item)
+	return
+}
+
+// GetChildEiaSteoClassifyById 获取子分类列表
+func GetChildEiaSteoClassifyById(classifyId int) (items []*BaseFromEiaSteoClassify, err error) {
+	sql := ` SELECT * FROM base_from_eia_steo_classify WHERE parent_id=? `
+	o := orm.NewOrmUsingDB("data")
+	_, err = o.Raw(sql, classifyId).QueryRows(&items)
+	return
+}
+
 type EiaSteoIndexListResp struct {
 	BaseFromEiaSteoIndexId    int                `orm:"column(base_from_eia_steo_index_id);pk"`
 	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
+}

+ 108 - 0
models/data_manage/base_from_ly_data.go

@@ -0,0 +1,108 @@
+// 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-1)*pageSize, 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
+}
+
+// GetLyLastUpdateTimeLastByIndexCode 根据指标编码查询 返回ModifyTime最后一条数据
+func GetLyLastUpdateTimeLastByIndexCode(indexCodes []string) (items []*BaseFromLyData, err error) {
+	o := orm.NewOrmUsingDB("data")
+
+	// 将 indexCodes 切片转换为逗号分隔的字符串
+	placeholders := strings.Repeat("?,", len(indexCodes)-1) + "?"
+
+	// 构造 SQL 查询
+	sql := `SELECT index_code, MAX(modify_time) AS modify_time
+            FROM base_from_ly_data
+            WHERE index_code IN (` + placeholders + `)
+            GROUP BY index_code`
+
+	// 执行 SQL 查询
+	_, err = o.Raw(sql, indexCodes).QueryRows(&items)
+	if err != nil {
+		return nil, err
+	}
+	return items, nil
+}
+
+// GetLyLastDataTimeByIndexCode 根据指标编码查询 返回data_time最后一条数据的value
+func GetLyLastDataTimeByIndexCode(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(data_time) AS data_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.data_time = t2.data_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 - 0
models/data_manage/edb_data_base.go

@@ -179,6 +179,8 @@ func GetEdbDataTableName(source, subSource int) (tableName string) {
 		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"
 	case utils.DATA_SOURCE_TRADE_ANALYSIS: // 持仓分析->92
 		tableName = "edb_data_trade_analysis"
 	default:

+ 4 - 0
models/data_manage/edb_info.go

@@ -228,6 +228,10 @@ type MysteelChemicalDataBatchAddCheckReq struct {
 	IndexCodes []string `form:"IndexCodes" description:"全选为false时, 该数组为选中; 全选为true时, 该数组为不选的指标"`
 }
 
+type EiaSteoDataBatchAddCheckReq struct {
+	IndexCodes []string `description:"指标编码"`
+}
+
 type AddEdbInfoReq struct {
 	Source     int    `description:"来源id"`
 	EdbCode    string `description:"指标编码"`

+ 99 - 0
routers/commentsRouter.go

@@ -2500,6 +2500,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",
@@ -4464,6 +4518,24 @@ func init() {
 
     beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:EdbInfoController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:EdbInfoController"],
         beego.ControllerComments{
+            Method: "EiaSteoBatchAdd",
+            Router: `/eia_steo/batch_add`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:EdbInfoController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:EdbInfoController"],
+        beego.ControllerComments{
+            Method: "EiaSteoBatchSearch",
+            Router: `/eia_steo/batch_search`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:EdbInfoController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:EdbInfoController"],
+        beego.ControllerComments{
             Method: "EiaSteoClassify",
             Router: `/eia_steo/classify`,
             AllowHTTPMethods: []string{"get"},
@@ -4482,6 +4554,33 @@ func init() {
 
     beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:EdbInfoController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:EdbInfoController"],
         beego.ControllerComments{
+            Method: "EiaSteoAdd",
+            Router: `/eia_steo/edb_info/add`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:EdbInfoController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:EdbInfoController"],
+        beego.ControllerComments{
+            Method: "EiaSteoAddCheck",
+            Router: `/eia_steo/edb_info/add_check`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:EdbInfoController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:EdbInfoController"],
+        beego.ControllerComments{
+            Method: "EiaSteoNameCheck",
+            Router: `/eia_steo/name_check`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:EdbInfoController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:EdbInfoController"],
+        beego.ControllerComments{
             Method: "EiaSteoSearchList",
             Router: `/eia_steo/search_list`,
             AllowHTTPMethods: []string{"get"},

+ 2 - 0
routers/router.go

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

+ 4 - 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 {
@@ -274,6 +276,8 @@ func RefreshEdbData(edbInfoId, source, subSource int, edbCode, startDate string)
 		urlStr = "sci99/refresh"
 	case utils.DATA_SOURCE_SCI_HQ:
 		urlStr = "sci_hq/refresh"
+	case utils.DATA_SOURCE_LY:
+		urlStr = "ly/refresh"
 	case utils.DATA_SOURCE_TRADE_ANALYSIS:
 		urlStr = "trade_analysis/edb/refresh"
 	default:

+ 79 - 0
services/data/base_from_eia_steo.go

@@ -0,0 +1,79 @@
+package data
+
+import (
+	"eta/eta_api/models/data_manage"
+	"eta/eta_api/utils"
+	"fmt"
+)
+
+func GetClassifyALLById(classifyId int) (items []*data_manage.BaseFromEiaSteoClassify, err error) {
+	classify, err := data_manage.GetEiaSteoClassifyById(classifyId)
+	if err != nil {
+		return
+	}
+	if classify.Level == 1 {
+		childClassify, er := data_manage.GetChildEiaSteoClassifyById(classifyId)
+		if er != nil {
+			err = er
+			return
+		}
+		items = append(items, childClassify...)
+	}
+	// 兼容之前部分指标在一级分类下的情况
+	if len(items) == 0 {
+		items = append(items, classify)
+	}
+	return
+}
+
+type EiaSteoIndexSource2EdbReq struct {
+	EdbCode       string
+	EdbName       string
+	Frequency     string
+	Unit          string
+	ClassifyId    int
+	AdminId       int
+	AdminRealName string
+}
+
+// EiaSteoIndexSource2Edb 新增eiaSteo数据源到指标库
+func EiaSteoIndexSource2Edb(req EiaSteoIndexSource2EdbReq, 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("EiaSteoIndexSource2Edb新增失败, Err: %s", err.Error())
+			fmt.Println(tips)
+			utils.FileLog.Info(tips)
+		}
+	}()
+	source := utils.DATA_SOURCE_EIA_STEO
+
+	// 是否新增过指标
+	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
+
+	// 新增指标库
+	edbInfo, e, msg, _ := EdbInfoAdd(source, utils.DATA_SUB_SOURCE_EDB, req.ClassifyId, req.EdbCode, req.EdbName, req.Frequency, req.Unit, startDate, endDate, req.AdminId, req.AdminRealName, lang)
+	if e != nil {
+		errMsg = msg
+		err = fmt.Errorf("EdbInfo: 新增指标失败, err: %s", e.Error())
+		return
+	}
+
+	edb = edbInfo
+
+	return
+}

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

+ 249 - 0
services/data/base_from_ly_index_service.go

@@ -0,0 +1,249 @@
+// 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.GetLyLastUpdateTimeLastByIndexCode(indexCodes)
+	if err != nil {
+		return nil, err
+	}
+	// 将lyIndexData转换为map
+	lyIndexDataMap := make(map[string]*data_manage.BaseFromLyData)
+	for _, v := range lyIndexData {
+		lyIndexDataMap[v.IndexCode] = v
+	}
+
+	lyData, err := data_manage.GetLyLastDataTimeByIndexCode(indexCodes)
+	if err != nil {
+		return nil, err
+	}
+	// 将lyData转换为map
+	lyDataMap := make(map[string]*data_manage.BaseFromLyData)
+	for _, v := range lyData {
+		lyDataMap[v.IndexCode] = v
+	}
+
+	// 查询指标库是否已添加  不做另外补偿维护index表中的edb_exist字段,直接去查,因为维护会改变指标库指标添加代码结构
+	edbInfoList, err := data_manage.GetEdbInfoByEdbCodeList(utils.DATA_SOURCE_LY, indexCodes)
+	if err != nil {
+		return nil, err
+	}
+	edbInfoMap := make(map[string]*data_manage.EdbInfo)
+	for _, v := range edbInfoList {
+		edbInfoMap[v.EdbCode] = v
+	}
+
+	if len(lyIndexData) > 0 {
+		for _, v := range lyIndexList {
+			if lyIndexDataMap[v.IndexCode] != nil {
+				toYmd := utils.TimeFormatToYmd(lyIndexDataMap[v.IndexCode].ModifyTime)
+				v.ModifyTimeMax = toYmd
+			}
+			if lyDataMap[v.IndexCode] != nil {
+				v.Value = lyDataMap[v.IndexCode].Value
+			}
+			if edbInfoMap[v.IndexCode] != nil {
+				v.EdbExist = utils.IS_YES
+			}
+		}
+	}
+
+	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
+	}*/
+
+	// EdbInfoAdd方法已经新增es,这里不需要再新增???
+	// 新增es
+	// go AddOrEditEdbInfoToEs(edbInfo.EdbInfoId)
+	return
+}

+ 20 - 0
services/data/chart_info.go

@@ -3901,6 +3901,11 @@ func SeasonChartData(dataList []*data_manage.ChartEdbInfoMapping, seasonExtraCon
 					if v.ChartLegend == strconv.Itoa(time.Now().Year()) {
 						continue
 					}
+					// 农历时dataTimeList的年份为最新年份,图例时间的年份才是真实年份
+					chartLegend,_ := strconv.Atoi(v.ChartLegend)
+					if chartLegend < startYear {
+						continue
+					}
 					for _, date := range dataTimeList {
 						dateTime, e := time.Parse(utils.FormatDate, date)
 						if e != nil {
@@ -4032,6 +4037,11 @@ func SeasonChartData(dataList []*data_manage.ChartEdbInfoMapping, seasonExtraCon
 						if dateTime.Year() < startYear {
 							continue
 						}
+						// 农历时dataTimeList的年份为最新年份,图例时间的年份才是真实年份
+						chartLegend,_ := strconv.Atoi(v.ChartLegend)
+						if chartLegend < startYear {
+							continue
+						}
 						// 月度的2月29号日期改为2月28日
 						if dateTime.Month() == 2 && dateTime.Day() == 29 {
 							dateTime = dateTime.AddDate(0, 0, -1)
@@ -4200,6 +4210,11 @@ func SeasonChartData(dataList []*data_manage.ChartEdbInfoMapping, seasonExtraCon
 					if dateTime.Year() < startYear {
 						continue
 					}
+					// 农历时dataTimeList的年份为最新年份,图例时间的年份才是真实年份
+					chartLegend,_ := strconv.Atoi(quarterDataList[i].ChartLegend)
+					if chartLegend < startYear {
+						continue
+					}
 					// 不包含2月29号
 					if dateTime.Month() == 2 && dateTime.Day() == 29 {
 						continue
@@ -4283,6 +4298,11 @@ func SeasonChartData(dataList []*data_manage.ChartEdbInfoMapping, seasonExtraCon
 					if dateTime.Year() < startYear {
 						continue
 					}
+					// 农历时dataTimeList的年份为最新年份,图例时间的年份才是真实年份
+					chartLegend,_ := strconv.Atoi(quarterDataList[i].ChartLegend)
+					if chartLegend < startYear {
+						continue
+					}
 					// 不包含2月29号
 					if dateTime.Month() == 2 && dateTime.Day() == 29 {
 						continue

+ 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:                  "粮油商务网",
 		utils.DATA_SOURCE_TRADE_ANALYSIS:      "持仓分析",
 	}
 

+ 2 - 0
services/data/excel/custom_analysis_edb.go

@@ -119,6 +119,7 @@ func HandleEdbSequenceVal(dateSequenceVal, dataSequenceVal []string) (newDateLis
 			v = strings.Replace(v, ",", "", -1)
 			// 过滤空格
 			v = strings.Replace(v, " ", "", -1)
+			v = strings.TrimSpace(v)
 
 			var tmpVal float64
 			if strings.Contains(v, "%") {
@@ -171,6 +172,7 @@ func HandleEdbSequenceVal(dateSequenceVal, dataSequenceVal []string) (newDateLis
 
 			// 过滤空格
 			v = strings.Replace(v, " ", "", -1)
+			v = strings.TrimSpace(v)
 			t1, tmpErr := dateparse.ParseAny(v)
 			if tmpErr != nil {
 				dateList = append(dateList, "")

+ 20 - 15
services/data/manual.go

@@ -432,6 +432,11 @@ func ImportManualData(path string, sysUser *system.Admin) (successCount, failCou
 			tmpValue = val
 			break
 		}
+		// 指标名称是空的,说明是空列
+		if v.IndexName == `` {
+			continue
+		}
+
 		if !strings.Contains(strings.Join(classifyNameStrList, ","), v.ClassName) {
 			failItem := &models.EdbdataImportFail{
 				ClassifyName: v.ClassName,
@@ -812,13 +817,13 @@ func getDataByTemplate1(sheet *xlsx.Sheet, sysUserId int) (indexDataList []Impor
 // @return err error
 // @return errMsg string
 func getDataByTemplate2(sheet *xlsx.Sheet, sysUserId int) (indexDataList []ImportManualIndexData, failDataList []*models.EdbdataImportFail, err error, errMsg string) {
-	fmt.Println("sheet name: ", sheet.Name)
+	//fmt.Println("sheet name: ", sheet.Name)
 	indexDataList = make([]ImportManualIndexData, 0)
 	failDataList = make([]*models.EdbdataImportFail, 0)
 
 	//遍历行读取
 	maxRow := sheet.MaxRow
-	fmt.Println("maxRow:", maxRow)
+	//fmt.Println("maxRow:", maxRow)
 
 	varietyList := make([]string, 0)
 	indexNameList := make([]string, 0)
@@ -896,24 +901,19 @@ func getDataByTemplate2(sheet *xlsx.Sheet, sysUserId int) (indexDataList []Impor
 
 		// 日期是否异常,异常的话,就跳过,进入下一行数据处理
 		var dateErr bool
+		var emptyDate bool
 
 		// 数据处理
 		for k, v := range cells {
 			if k == 0 {
+				// 空日期数据
+				if v.Value == `` {
+					emptyDate = true
+					continue
+				}
+
 				tmpCurrDate, tmpErr := getExcelDate(v.Value)
 				if tmpErr != nil {
-					// TODO 错误数据记录
-					//failItem := new(models.EdbdataImportFail)
-					//failItem.SysUserId = strconv.Itoa(sysUser.AdminId)
-					//failItem.ClassifyName = classifyName
-					//failItem.CreateDate = createDate
-					//failItem.SecName = secName
-					//failItem.Close = closeVal
-					//failItem.Remark = "日期格式异常"
-					//failItem.Frequency = frequency
-					//failItem.Unit = unit
-					//failDataList = append(failDataList, failItem)
-					//go utils.SendEmail(utils.APPNAME+"失败提醒", "导入数据 获取分类:Err:"+err.Error(), utils.EmailSendToUsers)
 					dateErr = true
 				}
 
@@ -922,7 +922,12 @@ func getDataByTemplate2(sheet *xlsx.Sheet, sysUserId int) (indexDataList []Impor
 			}
 			key := k - 1
 
-			// 日期异常,所以不处理该行了
+			// 空日期数据,那就不处理了,不记录该行错误信息
+			if emptyDate {
+				continue
+			}
+
+			// 日期异常,所以不处理该行了同时记录该行错误信息
 			if dateErr {
 				var indexName, unit, classifyName, frequency string
 				if key <= maxNameIndex {

+ 7 - 5
services/data/predict_edb_info.go

@@ -541,13 +541,15 @@ func MovePredictEdbInfo(edbInfoId, classifyId, prevEdbInfoId, nextEdbInfoId int,
 	//更新
 	if len(updateCol) > 0 {
 		err = edbInfo.Update(updateCol)
+		if err != nil {
+			errMsg = "移动失败"
+			err = errors.New("修改失败,Err:" + err.Error())
+			return
+		}
+		//添加es
+		AddOrEditEdbInfoToEs(edbInfo.EdbInfoId)
 
 	}
-	if err != nil {
-		errMsg = "移动失败"
-		err = errors.New("修改失败,Err:" + err.Error())
-		return
-	}
 	//新增操作日志
 	{
 		edbLog := new(data_manage.EdbInfoLog)

+ 7 - 0
services/data/trade_analysis/trade_analysis.go

@@ -240,6 +240,13 @@ func GetZhengzhouClassifyName(code string) (name string) {
 		name = "烧碱"
 		return
 	}
+	if strings.HasPrefix(code, "PR") {
+		name = "瓶片"
+		return
+	}
+	if name == "" {
+		utils.FileLog.Info(fmt.Sprintf("郑商所-合约暂未归类: %s", code))
+	}
 	return
 }
 

+ 31 - 11
services/data/trade_analysis/trade_analysis_data.go

@@ -14,6 +14,9 @@ import (
 // FormatCompanyTradeData2EdbMappings [公司-合约加总]转为指标数据
 func FormatCompanyTradeData2EdbMappings(companyTradeData []*tradeAnalysisModel.ContractCompanyTradeData, tradeType, dateType, dateTypeNum int, startDate, endDate string, chartEdbList []*data_manage.ChartSaveItem) (edbMappings []*data_manage.ChartEdbInfoMapping, chartName string, err error) {
 	edbMappings = make([]*data_manage.ChartEdbInfoMapping, 0)
+	if dateType <= 0 {
+		dateType = utils.DateTypeOneMonth
+	}
 
 	// 期货公司名称作为标识进行匹配
 	edbMap := make(map[string]*data_manage.ChartSaveItem)
@@ -71,35 +74,46 @@ func FormatCompanyTradeData2EdbMappings(companyTradeData []*tradeAnalysisModel.C
 		// 指标数据和最值
 		edbData := make([]*data_manage.EdbDataList, 0)
 		var minData, maxData float64
-		for dk, dv := range v.DataList {
+		var setMinMax bool
+		for _, dv := range v.DataList {
 			if dv.Date.Before(startTime) || dv.Date.After(endTime) {
 				continue
 			}
 
 			// 交易方向
-			var val float64
+			var (
+				val    float64
+				hasVal bool
+			)
 			if tradeType == tradeAnalysisModel.WarehouseBuyChartType {
 				if dv.BuyValType == tradeAnalysisModel.TradeDataTypeNull {
 					continue
 				}
+				hasVal = true
 				val = float64(dv.BuyVal)
 			}
 			if tradeType == tradeAnalysisModel.WarehouseSoldChartType {
 				if dv.SoldValType == tradeAnalysisModel.TradeDataTypeNull {
 					continue
 				}
+				hasVal = true
 				val = float64(dv.SoldVal)
 			}
 			if tradeType == tradeAnalysisModel.WarehousePureBuyChartType {
 				if dv.PureBuyValType == tradeAnalysisModel.TradeDataTypeNull {
 					continue
 				}
+				hasVal = true
 				val = float64(dv.PureBuyVal)
 			}
+			if !hasVal {
+				continue
+			}
 
-			if dk == 0 {
+			if !setMinMax {
 				minData = val
 				maxData = val
+				setMinMax = true
 			}
 			if val < minData {
 				minData = val
@@ -143,27 +157,27 @@ func GetOriginTradeData(exchange, classifyName string, contracts, companies []st
 		switch exchange {
 		case "zhengzhou":
 			for _, v := range list {
-				companyMap[v.ZhengzhouName] = v.CompanyName
+				companyMap[v.CompanyName] = v.ZhengzhouName
 			}
 		case "dalian":
 			for _, v := range list {
-				companyMap[v.DalianName] = v.CompanyName
+				companyMap[v.CompanyName] = v.DalianName
 			}
 		case "shanghai":
 			for _, v := range list {
-				companyMap[v.ShanghaiName] = v.CompanyName
+				companyMap[v.CompanyName] = v.ShanghaiName
 			}
 		case "cffex":
 			for _, v := range list {
-				companyMap[v.CffexName] = v.CompanyName
+				companyMap[v.CompanyName] = v.CffexName
 			}
 		case "ine":
 			for _, v := range list {
-				companyMap[v.IneName] = v.CompanyName
+				companyMap[v.CompanyName] = v.IneName
 			}
 		case "guangzhou":
 			for _, v := range list {
-				companyMap[v.GuangzhouName] = v.CompanyName
+				companyMap[v.CompanyName] = v.GuangzhouName
 			}
 		}
 	}
@@ -359,9 +373,15 @@ func GetOriginTradeData(exchange, classifyName string, contracts, companies []st
 	// 数据根据公司排序, 不然会随机乱
 	companyTradeData = make([]*tradeAnalysisModel.ContractCompanyTradeData, 0)
 	for _, v := range companies {
-		if mussyTradeData[v] != nil {
-			companyTradeData = append(companyTradeData, mussyTradeData[v])
+		// 没数据也需要加进去, 不然edbList会少
+		if mussyTradeData[v] == nil {
+			companyData := new(tradeAnalysisModel.ContractCompanyTradeData)
+			companyData.CompanyName = v
+			companyData.DataList = make([]*tradeAnalysisModel.ContractCompanyTradeDataList, 0)
+			companyTradeData = append(companyTradeData, companyData)
+			continue
 		}
+		companyTradeData = append(companyTradeData, mussyTradeData[v])
 	}
 	return
 }

+ 27 - 0
utils/common.go

@@ -683,6 +683,22 @@ func CheckPwd(pwd string) bool {
 	return flag
 }
 
+func CheckPwdV2(pwd string) bool {
+	var patternArr = []string{
+		".*[0-9]+.*", ".*[a-z]+.*", ".*[A-Z]+.*", ".*[@#$%^&+=.]+.*",
+	}
+	num := 0
+	for _, pattern := range patternArr {
+		if regexp.MustCompile(pattern).MatchString(pwd) {
+			num++
+		}
+	}
+	if len(pwd) < 8 {
+		num = 0
+	}
+	return num >= 3
+}
+
 func GetMonthStartAndEnd(myYear string, myMonth string) (startDate, endDate string) {
 	// 数字月份必须前置补零
 	if len(myMonth) == 1 {
@@ -870,6 +886,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())

+ 8 - 0
utils/constants.go

@@ -11,6 +11,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"          //完整时间格式
@@ -179,6 +180,7 @@ const (
 	DATA_SOURCE_SCI_HQ                               = 88       // 卓创红期->88
 	DATA_SOURCE_OILCHEM                              = 89       // 隆众资讯 -> 89
 	DATA_SOURCE_FENWEI                               = 77       // 汾渭数据->92
+	DATA_SOURCE_LY                                   = 91       // 粮油商务网
 	DATA_SOURCE_TRADE_ANALYSIS                       = 92       // 持仓分析
 )
 
@@ -332,6 +334,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,