فهرست منبع

Merge branch 'eta_2.2.5_rzd_1012@guomengyuan'

# Conflicts:
#	utils/constants.go
gmy 5 ماه پیش
والد
کامیت
48bd51054d

+ 708 - 0
controllers/data_manage/base_from_rzd_index_controller.go

@@ -0,0 +1,708 @@
+// 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"
+)
+
+// BaseFromRzdIndexController 睿姿得数据控制器
+type BaseFromRzdIndexController struct {
+	controllers.BaseAuthController
+}
+
+// RzdClassify
+// @Title 睿姿得数据分类
+// @Description 汾渭数据分类接口
+// @Success 200 {object} data_manage.BaseFromRzdClassifyResponse
+// @router /rzd/classify [get]
+func (this *BaseFromRzdIndexController) RzdClassify() {
+	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
+	}
+
+	classifies, e := data.RzdClassifyList()
+	if e != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取睿姿得数据分类失败, Err: " + e.Error()
+		return
+	}
+
+	br.Data = classifies
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+}
+
+// RzdIndexData
+// @Title 获取睿姿得数据
+// @Description 获取睿姿得数据
+// @Param   PageSize   query   int  true       "每页数据条数"
+// @Param   CurrentIndex   query   int  true       "当前页页码,从1开始"
+// @Param   ClassifyId   query   string  true       "分类id"
+// @Param   Frequency   query   string  true       "频率"
+// @Success 200
+// @router /rzd/index/data [get]
+func (this *BaseFromRzdIndexController) RzdIndexData() {
+	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")
+	var startSize int
+
+	if pageSize <= 0 {
+		pageSize = utils.PageSize20
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	startSize = utils.StartIndex(currentIndex, pageSize)
+
+	classifyId, _ := this.GetInt("ClassifyId")
+	if classifyId < 0 {
+		br.Msg = "请选择分类"
+		br.ErrMsg = "请选择分类"
+		return
+	}
+	frequency := this.GetString("Frequency")
+
+	resultList, err := data.RzdIndexData(classifyId, frequency, currentIndex, startSize, pageSize)
+	if err != nil {
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resultList
+}
+
+// RzdIndexDetail
+// @Title 获取睿姿得数据指标详情
+// @Description 获取睿姿得数据指标详情
+// @Param   IndexCode   query   string  true       "查询参数 指标id"
+// @Success 200
+// @router /rzd/index/detail [get]
+func (this *BaseFromRzdIndexController) RzdIndexDetail() {
+	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
+	}
+
+	indexCode := this.GetString("IndexCode")
+
+	pageSize, _ := this.GetInt("PageSize")
+	currentIndex, _ := this.GetInt("CurrentIndex")
+	var startSize int
+
+	if pageSize <= 0 {
+		pageSize = utils.PageSize20
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	startSize = utils.StartIndex(currentIndex, pageSize)
+
+	indexDetail, err := data.GetRzdIndexDetail(indexCode, currentIndex, startSize, pageSize)
+	if err != nil {
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = indexDetail
+}
+
+// RzdIndexList
+// @Title 获取睿姿得数据指标列表
+// @Description 获取睿姿得数据指标详情
+// @Param   searchParams   query   string  true       "查询参数 指标id/指标名称"
+// @Success 200
+// @router /rzd/index/list [get]
+func (this *BaseFromRzdIndexController) RzdIndexList() {
+	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
+	}
+
+	searchParams := this.GetString("SearchParams")
+
+	indexList, err := data.GetRzdIndexList(searchParams)
+	if err != nil {
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = indexList
+}
+
+// GetRzdFrequencyList
+// @Title 查询频率列表
+// @Description 查询频率列表
+// @Param   classifyId   query  int  false   "指标唯一编码"
+// @Success 200 {object} []string
+// @router /rzd/frequency/list [get]
+func (this *BaseFromRzdIndexController) GetRzdFrequencyList() {
+	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
+	}
+
+	classifyId, _ := this.GetInt("ClassifyId")
+	if classifyId < 0 {
+		br.Msg = "请选择分类"
+		br.ErrMsg = "请选择分类"
+		return
+	}
+	frequencyList, err := data.GetRzdIndexFrequency(classifyId)
+	if err != nil {
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = frequencyList
+}
+
+// RzdIndexAddValidate
+// @Title 新增加入到指标库校验
+// @Description 新增加入到指标库校验
+// @Param   req    body   data_manage.BaseFromFenWeiIndexBatchAddCheckReq     true        "请求参数"
+// @Success 200 {object} []data_manage.IndexCheckData
+// @router /rzd/index/add/validate [post]
+func (this *BaseFromRzdIndexController) RzdIndexAddValidate() {
+	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.BaseFromRzdIndexBatchAddCheckReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + e.Error()
+		return
+	}
+
+	// 校验指标编码是否存在
+	addValidate, err := data.RzdIndexAddValidate(req)
+	if err != nil {
+		br.Ret = 403
+		br.Success = false
+		br.Msg = err.Error()
+		return
+	}
+	br.Data = addValidate
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+// RzdIndexAdd
+// @Title 指标添加到指标库
+// @Description 指标添加到指标库
+// @Param   req    body   []data_manage.AddEdbInfoReq     true        "请求参数"
+// @Success 200 string "操作成功"
+// @router /rzd/index/add [post]
+func (this *BaseFromRzdIndexController) RzdIndexAdd() {
+	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_RZD_" + 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 = "批量添加指标数量不得超过" + strconv.Itoa(30) + "个"
+		return
+	}
+
+	indexNames := make([]string, 0)
+	resp := make([]*data_manage.RzdNameCheckResult, 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.RzdNameCheckResult{
+			IndexCode: index.EdbCode,
+			IndexName: index.EdbName,
+			Exist:     false,
+		})
+	}
+
+	// 指标名称重复校验
+	nameCheck, err := data.RzdIndexNameCheck(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 rzdIndexAddReq data_manage.RzdIndexAddReq
+		rzdIndexAddReq.EdbCode = v.EdbCode
+		rzdIndexAddReq.EdbName = v.EdbName
+		rzdIndexAddReq.Frequency = v.Frequency
+		rzdIndexAddReq.Unit = v.Unit
+		rzdIndexAddReq.ClassifyId = v.ClassifyId
+		rzdIndexAddReq.AdminId = sysUser.AdminId
+		rzdIndexAddReq.AdminRealName = sysUser.RealName
+
+		// 新增指标到指标库
+		edbInfo, e, errMsg, skip := data.RzdIndexAdd(rzdIndexAddReq, this.Lang)
+		if e != nil {
+			br.Msg = "操作失败"
+			if errMsg != "" {
+				br.Msg = errMsg
+			}
+			br.ErrMsg = e.Error()
+			return
+		}
+		if skip {
+			continue
+		}
+
+		// todo 下面两段代码能否抽离出来???
+		// 试用平台更新用户累计新增指标数
+		if utils.BusinessCode == utils.BusinessCodeSandbox {
+			go func() {
+				adminItem, e := system.GetSysAdminById(sysUser.AdminId)
+				if e != nil {
+					tips := fmt.Sprintf("试用平台更新用户累计新增指标数-获取用户失败, Err: " + e.Error())
+					utils.FileLog.Info(tips)
+					return
+				}
+				if adminItem.DepartmentName != "ETA试用客户" {
+					return
+				}
+				var ur etaTrialService.EtaTrialUserReq
+				ur.Mobile = adminItem.Mobile
+				_, _ = etaTrialService.UpdateUserIndexNum(ur)
+			}()
+		}
+
+		// 新增操作日志
+		{
+			edbLog := new(data_manage.EdbInfoLog)
+			edbLog.EdbInfoId = edbInfo.EdbInfoId
+			edbLog.SourceName = edbInfo.SourceName
+			edbLog.Source = edbInfo.Source
+			edbLog.EdbCode = edbInfo.EdbCode
+			edbLog.EdbName = edbInfo.EdbName
+			edbLog.ClassifyId = edbInfo.ClassifyId
+			edbLog.SysUserId = sysUser.AdminId
+			edbLog.SysUserRealName = sysUser.RealName
+			edbLog.CreateTime = time.Now()
+			edbLog.Content = string(this.Ctx.Input.RequestBody)
+			edbLog.Status = "新增指标"
+			edbLog.Method = this.Ctx.Input.URI()
+			go data_manage.AddEdbInfoLog(edbLog)
+		}
+	}
+
+	br.Msg = "操作成功"
+	br.Ret = 200
+	br.Success = true
+	br.IsAddLog = true
+}
+
+// RzdIndexDataExport
+// @Title 导出指标数据
+// @Description 导出指标数据
+// @Param  IndexCode     query   string     false        "指标编码"
+// @Param  ClassifyId     query   int     false        "分类ID"
+// @Success 200 string "操作成功"
+// @router /rzd/index/data/export [get]
+func (this *BaseFromRzdIndexController) RzdIndexDataExport() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请重新登录"
+		return
+	}
+
+	classifyId, _ := this.GetInt("ClassifyId") //分类
+	indexCode := this.GetString("IndexCode")   //指标唯一编码
+
+	if classifyId <= 0 {
+		br.Msg = "请选择分类"
+		return
+	}
+
+	dir, _ := os.Executable()
+	exPath := filepath.Dir(dir)
+
+	downLoadFilePath := exPath + "/" + time.Now().Format(utils.FormatDateTimeUnSpace) + ".xlsx"
+	xlsxFile := xlsx.NewFile()
+
+	classifyIdList, err := data.RzdClassifyRecursiveQuery(classifyId)
+	if err != nil {
+		br.Msg = "查询分类失败"
+		br.ErrMsg = "查询分类失败"
+		return
+	}
+	classifyIdList = append(classifyIdList, classifyId)
+
+	frequencies, err := data_manage.GetRzdIndexFrequency(classifyIdList)
+	if err != nil {
+		br.Msg = "查询频度失败"
+		br.ErrMsg = "查询频度失败"
+		return
+	}
+
+	fileName := `睿姿得数据`
+	if classifyId > 0 && indexCode == "" {
+		fenWeiClassify, err := data_manage.GetRzdClassifyItemByClassifyId(classifyId)
+		if err != nil {
+			return
+		}
+		fileName = fenWeiClassify.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 {
+		fenWeiIndices, err := data_manage.GetRzdIndexByCodeAndClassify(indexCode, classifyIdList, frequency)
+		if err != nil {
+			return
+		}
+		var sheet *xlsx.Sheet
+		if len(fenWeiIndices) > 0 {
+			sheetName := *frequency
+			if sheetName == "" {
+				sheetName = "无频度"
+			}
+			sheet, err = xlsxFile.AddSheet(sheetName)
+			if err != nil {
+				br.Msg = "新增Sheet失败"
+				br.ErrMsg = "新增Sheet失败,Err:" + err.Error()
+				return
+			}
+		} else {
+			continue
+		}
+
+		if indexCode != "" {
+			fileName = fenWeiIndices[0].IndexName
+		}
+
+		//获取指标数据
+		rowSecName := sheet.AddRow()
+		celSecName := rowSecName.AddCell()
+		celSecName.SetValue("指标名称/Metric Nome")
+		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.BaseFromRzdData)
+		var tradeCodeList []string
+		for _, v := range fenWeiIndices {
+			cellSenName := rowSecName.AddCell()
+			cellSenName.SetValue(v.IndexName)
+			celFrequency := rowFrequency.AddCell()
+			celFrequency.SetValue(v.Frequency)
+			celUnit := rowUnit.AddCell()
+			celUnit.SetValue(v.Unit)
+			rowModifyCell := rowModifyDate.AddCell()
+			updateTimeStr := utils.FormatDateString(v.ModifyTime)
+			rowModifyCell.SetValue(updateTimeStr)
+			tradeCodeList = append(tradeCodeList, v.IndexCode)
+
+			var dataList []*data_manage.BaseFromRzdData
+			dataList, err = data_manage.GetBaseFormRzdDataByIndexCode(v.IndexCode)
+			if err != nil && err.Error() != utils.ErrNoRow() {
+				br.ErrMsg = "GetBaseFormRzdDataByIndexCode,Err:" + err.Error()
+				br.Msg = "获取数据失败"
+				return
+			}
+			for _, item := range dataList {
+				if dataMap[item.IndexCode] == nil {
+					dataMap[item.IndexCode] = make(map[string]*data_manage.BaseFromRzdData)
+				}
+				dataMap[item.IndexCode][item.DataTime] = item
+			}
+		}
+
+		tradeCodeStr := strings.Join(tradeCodeList, "','")
+		tradeCodeStr = "'" + tradeCodeStr + "'"
+		dataTimeList, err := data_manage.GetRzdDataListByIndexCodes(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 fenWeiIndices {
+				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"
+}
+
+// GetRzdIndexInfo
+// @Title 添加指标-根据条件获取指标信息
+// @Description 添加指标-根据条件获取指标信息
+// @Param   KeyWord   query   string  false       "关键字"
+// @Param   ClassifyIds   query   string  false       "分类id"
+// @Param   Frequencies   query   string  false       "频率"
+// @Param   PageSize   query   int  false       "每页数据条数"
+// @Param   CurrentIndex   query   int  false       "当前页页码,从1开始"
+// @Success 200 {object} data_manage.BaseFromRzdIndexPage
+// @router /rzd/get/index/info [get]
+func (this *BaseFromRzdIndexController) GetRzdIndexInfo() {
+	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
+	}
+
+	keyWord := this.GetString("KeyWord")
+	classifyIds := this.GetString("ClassifyIds")
+	frequencies := this.GetString("Frequencies")
+
+	pageSize, _ := this.GetInt("PageSize")
+	currentIndex, _ := this.GetInt("CurrentIndex")
+	var startSize int
+
+	if pageSize <= 0 {
+		pageSize = utils.PageSize20
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	startSize = utils.StartIndex(currentIndex, pageSize)
+
+	var classifyIdList []string
+	var frequencyList []string
+	if classifyIds != "" {
+		classifyIdList = strings.Split(classifyIds, ",")
+	}
+	if frequencies != "" {
+		frequencyList = strings.Split(frequencies, ",")
+	}
+	indexInfoPage, err := data.GetRzdIndexInfo(keyWord, classifyIdList, frequencyList, currentIndex, startSize, pageSize)
+	if err != nil {
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = indexInfoPage
+}

+ 60 - 0
models/data_manage/base_from_rzd_classify.go

@@ -0,0 +1,60 @@
+// Package data_manage @Author gmy 2024/10/21 9:26:00
+package data_manage
+
+import (
+	"github.com/beego/beego/v2/client/orm"
+)
+
+type BaseFromRzdClassify struct {
+	BaseFromRzdClassifyId int    `orm:"column(base_from_rzd_classify_id);pk"`
+	CreateTime            string `orm:"column(create_time)"`
+	ModifyTime            string `orm:"column(modify_time)"`
+	ClassifyName          string `orm:"column(classify_name)"`
+	ParentId              int    `orm:"column(parent_id)"`
+	Sort                  int    `orm:"column(sort)"`
+	ClassifyNameEn        string `orm:"column(classify_name_en)"`
+}
+
+type BaseFromRzdClassifyResponse struct {
+	BaseFromRzdClassifyId int    `orm:"column(base_from_rzd_classify_id);pk"`
+	CreateTime            string `orm:"column(create_time)"`
+	ModifyTime            string `orm:"column(modify_time)"`
+	ClassifyName          string `orm:"column(classify_name)"`
+	ParentId              int    `orm:"column(parent_id)"`
+	Sort                  int    `orm:"column(sort)"`
+	ClassifyNameEn        string `orm:"column(classify_name_en)"`
+	IndexInfo             []*BaseFromRzdIndex
+	Child                 []*BaseFromRzdClassifyResponse
+}
+
+func init() {
+	orm.RegisterModel(new(BaseFromRzdClassify))
+}
+
+// GetAllRzdClassify 查询所有分类
+func GetAllRzdClassify() (items []*BaseFromRzdClassify, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT * FROM base_from_rzd_classify ORDER BY sort asc`
+	_, err = o.Raw(sql).QueryRows(&items)
+	return
+}
+
+// GetRzdClassifyItemByClassifyId 根据分类id查询分类信息
+func GetRzdClassifyItemByClassifyId(classifyId int) (item *BaseFromRzdClassify, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT * FROM base_from_rzd_classify WHERE base_from_rzd_classify_id = ?`
+
+	err = o.Raw(sql, classifyId).QueryRow(&item)
+	if err != nil {
+		return
+	}
+	return item, nil
+}
+
+func GetRzdClassifyItemByParentId(parentId int) (items []*BaseFromRzdClassify, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT * FROM base_from_rzd_classify WHERE parent_id = ?`
+
+	_, err = o.Raw(sql, parentId).QueryRows(&items)
+	return
+}

+ 115 - 0
models/data_manage/base_from_rzd_data.go

@@ -0,0 +1,115 @@
+// Package data_manage @Author gmy 2024/8/7 9:50:00
+package data_manage
+
+import (
+	"eta/eta_api/utils"
+	"github.com/beego/beego/v2/client/orm"
+)
+
+type BaseFromRzdData struct {
+	BaseFromRzdDataId  int     `orm:"column(base_from_rzd_data_id);pk"`
+	BaseFromRzdIndexId int     `orm:"column(base_from_rzd_index_id)"`
+	CreateTime         string  `orm:"column(create_time)"`
+	DataTime           string  `orm:"column(data_time)"`
+	IndexCode          string  `orm:"column(index_code)"`
+	ModifyTime         string  `orm:"column(modify_time)"`
+	Value              float64 `orm:"column(value)"`
+}
+
+// RzdIndexAddReq 指标添加vo
+type RzdIndexAddReq struct {
+	EdbCode       string `description:"指标编码"`
+	EdbName       string `description:"指标名称"`
+	Frequency     string `description:"频度"`
+	Unit          string `description:"单位"`
+	ClassifyId    int    `description:"分类ID"`
+	AdminId       int    `description:"管理员ID"`
+	AdminRealName string `description:"管理员名称"`
+}
+
+type RzdIndexDataCountGroup struct {
+	IndexCode string
+	Count     int
+}
+
+func init() {
+	orm.RegisterModel(new(BaseFromRzdData))
+}
+
+func GetRzdIndexDataCountGroup(indexCodes []string) (items []*RzdIndexDataCountGroup, err error) {
+	if len(indexCodes) <= 0 {
+		return
+	}
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT COUNT(1) AS count, index_code FROM base_from_rzd_data WHERE index_code IN (` + utils.GetOrmInReplace(len(indexCodes)) + `) GROUP BY index_code`
+	_, err = o.Raw(sql, indexCodes).QueryRows(&items)
+	return
+}
+
+func GetRzdIndexData(indexCode string, startSize, pageSize int) (items []*BaseFromRzdData, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT *  FROM base_from_rzd_data WHERE index_code=? ORDER BY data_time DESC LIMIT ?,? `
+	_, err = o.Raw(sql, indexCode, startSize, pageSize).QueryRows(&items)
+	return
+}
+
+// GetBaseFormRzdDataByIndexCode 根据指标编码查询
+func GetBaseFormRzdDataByIndexCode(indexCode string) (items []*BaseFromRzdData, err error) {
+	sql := `SELECT * FROM base_from_rzd_data WHERE index_code=? ORDER BY data_time desc`
+	o := orm.NewOrmUsingDB("data")
+	_, err = o.Raw(sql, indexCode).QueryRows(&items)
+	return
+}
+
+func GetBaseFormRzdDataByConditionCount(condition string, pars interface{}) (count int, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT count(1) FROM base_from_rzd_data WHERE 1=1  `
+	if condition != "" {
+		sql += condition
+	}
+	err = o.Raw(sql, pars).QueryRow(&count)
+	if err != nil {
+		return 0, err
+	}
+	return
+}
+
+func GetBaseFormRzdDataByCondition(condition string, pars interface{}) (items []*BaseFromRzdData, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT * FROM base_from_rzd_data WHERE 1=1  `
+	if condition != "" {
+		sql += condition
+	}
+	_, err = o.Raw(sql, pars).QueryRows(&items)
+	return
+}
+
+// GetRzdDataListByIndexCodes 根据指标编码查询
+func GetRzdDataListByIndexCodes(IndexCodes string) (items []string, err error) {
+	sql := ` SELECT data_time FROM base_from_rzd_data WHERE index_code IN(` + IndexCodes + `)  GROUP BY data_time DESC `
+	o := orm.NewOrmUsingDB("data")
+	_, err = o.Raw(sql).QueryRows(&items)
+	return
+}
+
+// GetRzdLastUpdateTimeLastByIndexCode 根据指标编码查询 返回ModifyTime最后一条数据
+func GetRzdLastUpdateTimeLastByIndexCode(indexCodes []string) (items []*BaseFromRzdData, err error) {
+	o := orm.NewOrmUsingDB("data")
+
+	// 构造 SQL 查询
+	sql := `SELECT t1.index_code, t1.data_time, t2.value
+			FROM (
+    			SELECT index_code, MAX(data_time) AS data_time
+   				 FROM base_from_rzd_data
+    			WHERE index_code IN (` + utils.GetOrmInReplace(len(indexCodes)) + `)
+    			GROUP BY index_code
+			) AS t1
+			JOIN base_from_rzd_data AS 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
+}

+ 213 - 0
models/data_manage/base_from_rzd_index.go

@@ -0,0 +1,213 @@
+// Package data_manage
+// @Author gmy 2024/8/7 9:38:00
+package data_manage
+
+import (
+	"eta/eta_api/utils"
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
+	"github.com/rdlucklib/rdluck_tools/paging"
+)
+
+type BaseFromRzdIndex struct {
+	BaseFromRzdIndexId    int    `orm:"column(base_from_rzd_index_id);pk"`
+	CreateTime            string `orm:"column(create_time)"`
+	ModifyTime            string `orm:"column(modify_time)"`
+	BaseFromRzdClassifyId int    `orm:"column(base_from_rzd_classify_id)"`
+	IndexCode             string `orm:"column(index_code)"`
+	IndexName             string `orm:"column(index_name)"`
+	Frequency             string `orm:"column(frequency)"`
+	Unit                  string `orm:"column(unit)"`
+}
+
+type BaseFromRzdIndexAndData struct {
+	BaseFromRzdIndexId    int     `orm:"column(base_from_rzd_index_id);pk"`
+	CreateTime            string  `orm:"column(create_time)"`
+	ModifyTime            string  `orm:"column(modify_time)"`
+	BaseFromRzdClassifyId int     `orm:"column(base_from_rzd_classify_id)"`
+	IndexCode             string  `orm:"column(index_code)"`
+	IndexName             string  `orm:"column(index_name)"`
+	Frequency             string  `orm:"column(frequency)"`
+	Unit                  string  `orm:"column(unit)"`
+	ModifyTimeMax         string  `json:"modify_time_max" description:"最后修改时间"`
+	Value                 float64 `orm:"column(value)" description:"数据值"`
+}
+
+type BaseFromRzdIndexPage struct {
+	List   []*BaseFromRzdIndexAndData `description:"指标列表"`
+	Paging *paging.PagingItem         `description:"分页数据"`
+}
+
+type BaseFromRzdIndexList struct {
+	BaseFromRzdIndexId    int    `orm:"column(base_from_rzd_index_id);pk"`
+	CreateTime            string `orm:"column(create_time)"`
+	ModifyTime            string `orm:"column(modify_time)"`
+	BaseFromRzdClassifyId int    `orm:"column(base_from_rzd_classify_id)"`
+	IndexCode             string `orm:"column(index_code)"`
+	IndexName             string `orm:"column(index_name)"`
+	Frequency             string `orm:"column(frequency)"`
+	Unit                  string `orm:"column(unit)"`
+	DataList              []*BaseFromRzdData
+	Paging                *paging.PagingItem `description:"分页数据"`
+	EdbInfoId             int                `description:"指标库主键id"`
+}
+
+// RzdNameCheckResult 校验名称是否存在
+type RzdNameCheckResult struct {
+	IndexCode string `from:"EdbCode" description:"edb编码"`
+	IndexName string `from:"EdbName" description:"edb名称"`
+	Exist     bool
+}
+
+// RzdIndexCheckData 校验编码是否存在
+type RzdIndexCheckData 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"`
+}
+
+// BaseFromRzdIndexBatchAddCheckReq 校验编码是否存在请求参数
+type BaseFromRzdIndexBatchAddCheckReq struct {
+	IndexCodes     []string `form:"IndexCodes" description:"指标编码列表"`
+	ClassifyIdList []int    `description:"分类id"`
+	FrequencyList  []string `description:"频度"`
+	SearchParams   string   `description:"搜索参数 指标编码/指标名称"`
+	IsCheckAll     bool     `description:"是否全选"`
+}
+
+func init() {
+	orm.RegisterModel(new(BaseFromRzdIndex))
+}
+
+// GetRzdIndexByClassifyIds 根据分类id获取指标信息
+func GetRzdIndexByClassifyIds(classifyIds []int) (items []*BaseFromRzdIndex, err error) {
+	o := orm.NewOrmUsingDB("data")
+
+	sql := fmt.Sprintf(`SELECT * FROM base_from_rzd_index WHERE base_from_rzd_classify_id IN (`+utils.GetOrmInReplace(len(classifyIds))) + `)`
+	_, err = o.Raw(sql, classifyIds).QueryRows(&items)
+	if err != nil {
+		return nil, err
+	}
+
+	return items, nil
+}
+
+func GetRzdIndex(condition string, pars interface{}) (items []*BaseFromRzdIndexList, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT * FROM base_from_rzd_index WHERE 1=1  `
+	if condition != "" {
+		sql += condition
+	}
+	sql += ` ORDER BY base_from_rzd_index_id asc`
+	_, err = o.Raw(sql, pars).QueryRows(&items)
+	return
+}
+
+func GetRzdIndexNotExistEdbInfoCount(condition string, pars interface{}) (count int, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT count(1) FROM base_from_rzd_index WHERE index_code not in (select edb_code from edb_info) `
+	if condition != "" {
+		sql += condition
+	}
+	err = o.Raw(sql, pars).QueryRow(&count)
+	return
+}
+
+func GetRzdIndexNotExistEdbInfoPage(condition string, pars interface{}) (items []*BaseFromRzdIndexAndData, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT * FROM base_from_rzd_index WHERE index_code not in (select edb_code from edb_info) `
+	if condition != "" {
+		sql += condition
+	}
+	_, err = o.Raw(sql, pars).QueryRows(&items)
+	return
+}
+
+// GetRzdIndexFrequency 获取指标频度
+func GetRzdIndexFrequency(classifyIdList []int) (items []*string, err error) {
+	sql := `SELECT DISTINCT frequency 
+        FROM base_from_rzd_index 
+        WHERE frequency is not null`
+
+	// 如果 classifyId > 0,则添加该条件
+	if len(classifyIdList) > 0 {
+		sql += ` AND base_from_rzd_classify_id in (` + utils.GetOrmInReplace(len(classifyIdList)) + `)`
+	}
+
+	sql += ` ORDER BY FIELD(frequency, '日度', '周度', '月度', '季度', '半年度', '年度')`
+
+	o := orm.NewOrmUsingDB("data")
+	if len(classifyIdList) > 0 {
+		_, err = o.Raw(sql, classifyIdList).QueryRows(&items)
+	} else {
+		_, err = o.Raw(sql).QueryRows(&items)
+	}
+
+	return items, err
+}
+
+// GetRzdIndexByCodeAndClassify 根据指标编码和分类查询 indexCode非必传
+func GetRzdIndexByCodeAndClassify(indexCode string, classifyIdList []int, frequency *string) (items []*BaseFromRzdIndex, 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_rzd_index AS a
+			INNER JOIN base_from_rzd_data AS b ON a.base_from_rzd_index_id = b.base_from_rzd_index_id
+			WHERE 1=1`
+
+	var params []interface{}
+
+	if len(classifyIdList) > 0 {
+		sql += ` AND a.base_from_rzd_classify_id in (` + utils.GetOrmInReplace(len(classifyIdList)) + `)`
+		for _, id := range classifyIdList {
+			params = append(params, id)
+		}
+	}
+
+	// 如果 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
+}
+
+// GetRzdIndexInfoCount 分页查询指标信息行数
+func GetRzdIndexInfoCount(condition string, pars []interface{}) (count int, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT count(1) FROM base_from_rzd_index WHERE index_code not in (select edb_code from edb_info) `
+	if condition != "" {
+		sql += condition
+	}
+	err = o.Raw(sql, pars).QueryRow(&count)
+	return
+}
+
+// GetRzdIndexInfoPage 分页查询指标信息
+func GetRzdIndexInfoPage(condition string, pars []interface{}) (items []*BaseFromRzdIndexAndData, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT * FROM base_from_rzd_index WHERE index_code not in (select edb_code from edb_info) `
+	if condition != "" {
+		sql += condition
+	}
+	_, err = o.Raw(sql, pars).QueryRows(&items)
+	return
+
+}

+ 81 - 0
routers/commentsRouter.go

@@ -2635,6 +2635,87 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:BaseFromRzdIndexController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:BaseFromRzdIndexController"],
+        beego.ControllerComments{
+            Method: "RzdClassify",
+            Router: `/rzd/classify`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:BaseFromRzdIndexController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:BaseFromRzdIndexController"],
+        beego.ControllerComments{
+            Method: "GetRzdFrequencyList",
+            Router: `/rzd/frequency/list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:BaseFromRzdIndexController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:BaseFromRzdIndexController"],
+        beego.ControllerComments{
+            Method: "GetRzdIndexInfo",
+            Router: `/rzd/get/index/info`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:BaseFromRzdIndexController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:BaseFromRzdIndexController"],
+        beego.ControllerComments{
+            Method: "RzdIndexAdd",
+            Router: `/rzd/index/add`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:BaseFromRzdIndexController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:BaseFromRzdIndexController"],
+        beego.ControllerComments{
+            Method: "RzdIndexAddValidate",
+            Router: `/rzd/index/add/validate`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:BaseFromRzdIndexController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:BaseFromRzdIndexController"],
+        beego.ControllerComments{
+            Method: "RzdIndexData",
+            Router: `/rzd/index/data`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:BaseFromRzdIndexController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:BaseFromRzdIndexController"],
+        beego.ControllerComments{
+            Method: "RzdIndexDataExport",
+            Router: `/rzd/index/data/export`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:BaseFromRzdIndexController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:BaseFromRzdIndexController"],
+        beego.ControllerComments{
+            Method: "RzdIndexDetail",
+            Router: `/rzd/index/detail`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:BaseFromRzdIndexController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:BaseFromRzdIndexController"],
+        beego.ControllerComments{
+            Method: "RzdIndexList",
+            Router: `/rzd/index/list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:BaseFromThsHfController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:BaseFromThsHfController"],
         beego.ControllerComments{
             Method: "ClassifyAdd",

+ 1 - 0
routers/router.go

@@ -182,6 +182,7 @@ func init() {
 				&data_manage.SciHqDataController{},
 				&data_manage.BaseFromLyClassifyController{},
 				&data_manage.BaseFromLyIndexController{},
+				&data_manage.BaseFromRzdIndexController{},
 			),
 		),
 		web.NSNamespace("/my_chart",

+ 2 - 0
services/data/base_edb_lib.go

@@ -78,6 +78,8 @@ func AddEdbData(source int, edbCode, frequency string) (resp *models.BaseRespons
 		urlStr = "sci_hq/add"
 	case utils.DATA_SOURCE_LY:
 		urlStr = "ly/add"
+	case utils.DATA_SOURCE_RZD:
+		urlStr = "rzd/add"
 	default:
 		edbSource := data_manage.EdbSourceIdMap[source]
 		if edbSource != nil {

+ 93 - 0
services/data/base_from_rzd_classify_service.go

@@ -0,0 +1,93 @@
+// Package data
+// @Author gmy 2024/8/12 16:09:00
+package data
+
+import (
+	"eta/eta_api/models/data_manage"
+	"sort"
+)
+
+// RzdClassifyList 获取分类列表 包含 分类下的指标名称
+func RzdClassifyList() ([]*data_manage.BaseFromRzdClassifyResponse, error) {
+	// step_1 获取分类列表
+	rzdClassify, err := data_manage.GetAllRzdClassify()
+	if err != nil {
+		return nil, err
+	}
+
+	// step_2 分类id列表
+	classifyIds := make([]int, 0)
+	for _, v := range rzdClassify {
+		classifyIds = append(classifyIds, v.BaseFromRzdClassifyId)
+	}
+
+	// step_3 获取分类下的指标
+	rzdIndices, err := data_manage.GetRzdIndexByClassifyIds(classifyIds)
+	if err != nil {
+		return nil, err
+	}
+	// step_4 封装返回
+	classifyMap := make(map[int]*data_manage.BaseFromRzdClassifyResponse)
+	indexMap := make(map[int][]*data_manage.BaseFromRzdIndex)
+
+	// 创建分类响应映射
+	for _, classify := range rzdClassify {
+		classifyMap[classify.BaseFromRzdClassifyId] = &data_manage.BaseFromRzdClassifyResponse{
+			BaseFromRzdClassifyId: classify.BaseFromRzdClassifyId,
+			CreateTime:            classify.CreateTime,
+			ModifyTime:            classify.ModifyTime,
+			ClassifyName:          classify.ClassifyName,
+			ParentId:              classify.ParentId,
+			Sort:                  classify.Sort,
+			ClassifyNameEn:        classify.ClassifyNameEn,
+		}
+	}
+
+	// 将指标归类到各自的分类
+	for _, index := range rzdIndices {
+		indexMap[index.BaseFromRzdClassifyId] = append(indexMap[index.BaseFromRzdClassifyId], index)
+	}
+
+	// step_5 组装最终结果
+	rzdClassifyAndIndexInfos := make([]*data_manage.BaseFromRzdClassifyResponse, 0)
+
+	for _, classifyResponse := range classifyMap {
+		if classifyResponse.ParentId == 0 { // 根分类
+			// 添加指标信息
+			if indices, exists := indexMap[classifyResponse.BaseFromRzdClassifyId]; exists {
+				classifyResponse.IndexInfo = indices
+			}
+			rzdClassifyAndIndexInfos = append(rzdClassifyAndIndexInfos, classifyResponse)
+		} else {
+			// 查找父分类并添加到其子分类中
+			if parent, exists := classifyMap[classifyResponse.ParentId]; exists {
+				// 添加指标信息
+				if indices, exists := indexMap[classifyResponse.BaseFromRzdClassifyId]; exists {
+					classifyResponse.IndexInfo = indices
+				}
+				parent.Child = append(parent.Child, classifyResponse)
+			}
+		}
+	}
+	sort.Slice(rzdClassifyAndIndexInfos, func(i, j int) bool {
+		return rzdClassifyAndIndexInfos[i].Sort < rzdClassifyAndIndexInfos[j].Sort
+	})
+
+	for _, info := range rzdClassifyAndIndexInfos {
+		sort.Slice(info.Child, func(i, j int) bool {
+			return info.Child[i].Sort < info.Child[j].Sort
+		})
+	}
+
+	return rzdClassifyAndIndexInfos, nil
+}
+
+// GetRzdClassifyItemByParentId 根据分类id获取分类信息
+func GetRzdClassifyItemByParentId(classifyId int) ([]*data_manage.BaseFromRzdClassify, error) {
+	rzdClassify, err := data_manage.GetRzdClassifyItemByParentId(classifyId)
+	if err != nil {
+		return nil, err
+	}
+
+	return rzdClassify, nil
+}

+ 444 - 0
services/data/base_from_rzd_index_service.go

@@ -0,0 +1,444 @@
+// Package data
+// @Author gmy 2024/8/22 9:44:00
+package data
+
+import (
+	"eta/eta_api/models/data_manage"
+	"eta/eta_api/utils"
+	"fmt"
+	"github.com/rdlucklib/rdluck_tools/paging"
+)
+
+// RzdIndexData 获取睿姿得指标数据
+func RzdIndexData(classifyId int, frequency string, currentIndex, startSize, pageSize int) (dataList []*data_manage.BaseFromRzdIndexList, err error) {
+
+	// 获取指标
+	var condition string
+	var pars []interface{}
+	if classifyId >= 0 {
+		// 递归查询子集分类
+		classifyIdList, err := RzdClassifyRecursiveQuery(classifyId)
+		if err != nil {
+			return nil, err
+		}
+		classifyIdList = append(classifyIdList, classifyId)
+
+		interfaceClassifyIdList := make([]interface{}, len(classifyIdList))
+		for i, id := range classifyIdList {
+			interfaceClassifyIdList[i] = id
+		}
+
+		condition += ` AND base_from_rzd_classify_id in (` + utils.GetOrmInReplace(len(classifyIdList)) + `)`
+		pars = append(pars, interfaceClassifyIdList...)
+	}
+
+	if frequency != "" {
+		condition += ` AND frequency=? `
+		pars = append(pars, frequency)
+	}
+
+	indexes, err := data_manage.GetRzdIndex(condition, pars)
+	if err != nil {
+		return nil, err
+	}
+
+	indexCodes := make([]string, 0)
+	for _, v := range indexes {
+		indexCodes = append(indexCodes, v.IndexCode)
+	}
+	indexCounts, e := data_manage.GetRzdIndexDataCountGroup(indexCodes)
+	if e != nil {
+		return nil, err
+	}
+	countMap := make(map[string]int)
+	for _, v := range indexCounts {
+		countMap[v.IndexCode] = v.Count
+	}
+
+	// 判断是否存在于指标库
+	edbCodeList, err := data_manage.GetEdbInfoByEdbCodeList(utils.DATA_SOURCE_RZD, indexCodes)
+	if err != nil {
+		return
+	}
+	edbCodeMap := make(map[string]*data_manage.EdbInfo)
+	for _, v := range edbCodeList {
+		edbCodeMap[v.EdbCode] = v
+	}
+
+	resultList := make([]*data_manage.BaseFromRzdIndexList, 0)
+	for _, v := range indexes {
+		product := new(data_manage.BaseFromRzdIndexList)
+		product.BaseFromRzdIndexId = v.BaseFromRzdIndexId
+		product.BaseFromRzdClassifyId = v.BaseFromRzdClassifyId
+		product.Unit = v.Unit
+		product.IndexCode = v.IndexCode
+		product.IndexName = v.IndexName
+		product.Frequency = v.Frequency
+		product.CreateTime = v.CreateTime
+		product.ModifyTime = v.ModifyTime
+
+		edbInfo := edbCodeMap[v.IndexCode]
+		if edbInfo != nil {
+			product.EdbInfoId = edbInfo.EdbInfoId
+		}
+
+		total := countMap[v.IndexCode]
+		page := paging.GetPaging(currentIndex, pageSize, total)
+		indexDataList, e := data_manage.GetRzdIndexData(v.IndexCode, startSize, pageSize)
+		if e != nil {
+			return nil, err
+		}
+		if indexDataList == nil {
+			indexDataList = make([]*data_manage.BaseFromRzdData, 0)
+		}
+		product.DataList = indexDataList
+		product.Paging = page
+		resultList = append(resultList, product)
+	}
+
+	return resultList, nil
+}
+
+// RzdClassifyRecursiveQuery 递归查询分类
+func RzdClassifyRecursiveQuery(classifyId int) ([]int, error) {
+	var classifyIdList []int
+
+	// 查询当前分类 ID 的子分类
+	rzdClassifyList, err := GetRzdClassifyItemByParentId(classifyId)
+	if err != nil {
+		return nil, err
+	}
+
+	// 遍历子分类
+	for _, classify := range rzdClassifyList {
+		// 将当前子分类的 ID 添加到列表中
+		classifyIdList = append(classifyIdList, classify.BaseFromRzdClassifyId)
+
+		// 递归查询当前子分类的子分类
+		childIds, err := RzdClassifyRecursiveQuery(classify.BaseFromRzdClassifyId)
+		if err != nil {
+			return nil, err
+		}
+
+		// 合并子分类的 ID
+		classifyIdList = append(classifyIdList, childIds...)
+	}
+
+	return classifyIdList, nil
+}
+
+func GetRzdIndexFrequency(classify int) ([]*string, error) {
+
+	classifyIdList, err := RzdClassifyRecursiveQuery(classify)
+	if err != nil {
+		return nil, err
+	}
+	classifyIdList = append(classifyIdList, classify)
+
+	frequencyNameList, err := data_manage.GetRzdIndexFrequency(classifyIdList)
+	if err != nil {
+		return nil, err
+	}
+	return frequencyNameList, nil
+}
+
+// RzdIndexAddValidate 指标添加校验
+func RzdIndexAddValidate(req *data_manage.BaseFromRzdIndexBatchAddCheckReq) ([]*data_manage.BaseFromRzdIndexAndData, error) {
+	var condition string
+	var pars []interface{}
+
+	if req.IsCheckAll {
+		if len(req.ClassifyIdList) > 0 {
+			condition += ` AND base_from_rzd_classify_id in (` + utils.GetOrmInReplace(len(req.ClassifyIdList)) + `)`
+			for _, id := range req.ClassifyIdList {
+				pars = append(pars, id)
+			}
+		}
+		if len(req.FrequencyList) > 0 {
+			condition += ` AND frequency in (` + utils.GetOrmInReplace(len(req.FrequencyList)) + `)`
+			for _, frequency := range req.FrequencyList {
+				pars = append(pars, frequency)
+			}
+		}
+		if req.SearchParams != "" {
+			condition += ` AND (index_name like ? or index_code like ?)`
+			pars = append(pars, "%"+req.SearchParams+"%", "%"+req.SearchParams+"%")
+		}
+		if len(req.IndexCodes) > 0 {
+			condition += ` AND index_code not in (` + utils.GetOrmInReplace(len(req.IndexCodes)) + `)`
+			for _, code := range req.IndexCodes {
+				pars = append(pars, code)
+			}
+		}
+	} else {
+		if len(req.IndexCodes) > 0 {
+			condition += ` AND index_code in (` + utils.GetOrmInReplace(len(req.IndexCodes)) + `)`
+			for _, code := range req.IndexCodes {
+				pars = append(pars, code)
+			}
+		}
+	}
+
+	count, err := data_manage.GetRzdIndexNotExistEdbInfoCount(condition, pars)
+	if err != nil {
+		return nil, err
+	}
+
+	if count > 30 {
+		return nil, fmt.Errorf("批量添加指标数量不得超过30个")
+	}
+
+	condition += ` ORDER BY base_from_rzd_index_id asc`
+
+	indexList, err := data_manage.GetRzdIndexNotExistEdbInfoPage(condition, pars)
+	if err != nil {
+		return nil, err
+	}
+	return indexList, nil
+}
+
+// RzdIndexNameCheck 指标名称校验
+func RzdIndexNameCheck(indexNames []string, resp []*data_manage.RzdNameCheckResult) ([]*data_manage.RzdNameCheckResult, 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
+}
+
+// RzdIndexAdd 批量添加指标
+func RzdIndexAdd(req data_manage.RzdIndexAddReq, 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("ruizide指标数据新增失败, Err: %s", err.Error())
+			utils.FileLog.Info(tips)
+		}
+	}()
+	source := utils.DATA_SOURCE_RZD
+
+	// 是否已有指标数据
+	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
+
+	// EdbInfoAdd方法已经新增es,这里不需要再新增???
+	// 新增es
+	// go AddOrEditEdbInfoToEs(edbInfo.EdbInfoId)
+	return
+}
+
+// GetRzdIndexInfo 获取指标信息-分页
+func GetRzdIndexInfo(keyWord string, classifyIdList []string, frequencyList []string, currentIndex, startSize, pageSize int) (rzdIndexInfoList *data_manage.BaseFromRzdIndexPage, err error) {
+
+	// 获取指标
+	var condition string
+	var pars []interface{}
+	if keyWord != "" {
+		condition += ` AND (index_name like ? or index_code like ?)`
+		pars = append(pars, "%"+keyWord+"%", "%"+keyWord+"%")
+	}
+	if len(classifyIdList) > 0 {
+		condition += ` AND base_from_rzd_classify_id IN (`
+		for _, v := range classifyIdList {
+			condition += `?,`
+			pars = append(pars, v)
+		}
+		condition = condition[:len(condition)-1] + `)`
+	}
+	if len(frequencyList) > 0 {
+		condition += ` AND frequency IN (`
+		for _, v := range frequencyList {
+			condition += `?,`
+			pars = append(pars, v)
+		}
+		condition = condition[:len(condition)-1] + `)`
+	}
+
+	count, err := data_manage.GetRzdIndexInfoCount(condition, pars)
+	if err != nil {
+		return nil, err
+	}
+	indexPage := data_manage.BaseFromRzdIndexPage{}
+	page := paging.GetPaging(currentIndex, pageSize, count)
+	if count <= 0 {
+		indexPage.Paging = page
+		return &indexPage, nil
+	}
+
+	condition += ` ORDER BY base_from_rzd_index_id asc`
+
+	// 分页
+	condition += ` LIMIT ?, ?`
+	pars = append(pars, startSize, pageSize)
+
+	indexInfoPage, err := data_manage.GetRzdIndexInfoPage(condition, pars)
+	if err != nil {
+		return nil, err
+	}
+	var indexCodes []string
+	for _, indexInfo := range indexInfoPage {
+		indexCodes = append(indexCodes, indexInfo.IndexCode)
+	}
+	IndexDataList, err := data_manage.GetRzdLastUpdateTimeLastByIndexCode(indexCodes)
+	if err != nil {
+		return nil, err
+	}
+	var indexDataMap = make(map[string]*data_manage.BaseFromRzdData, 0)
+	for _, data := range IndexDataList {
+		indexDataMap[data.IndexCode] = data
+	}
+	for _, indexInfo := range indexInfoPage {
+		if indexDataMap[indexInfo.IndexCode] == nil {
+			continue
+		}
+		indexInfo.ModifyTimeMax = indexDataMap[indexInfo.IndexCode].DataTime
+		indexInfo.Value = indexDataMap[indexInfo.IndexCode].Value
+	}
+
+	indexPage.List = indexInfoPage
+	indexPage.Paging = page
+	return &indexPage, nil
+}
+
+// GetRzdIndexDetail 获取指标详情
+func GetRzdIndexDetail(indexCode string, currentIndex, startSize, pageSize int) (rzdIndexInfoList *data_manage.BaseFromRzdIndexList, err error) {
+
+	// 获取指标
+	var condition string
+	var pars []interface{}
+	if indexCode != "" {
+		condition += ` and index_code = ?`
+		pars = append(pars, indexCode)
+	}
+	rzdIndexList, err := data_manage.GetRzdIndex(condition, pars)
+	if err != nil {
+		return nil, err
+	}
+
+	var rzdIndex *data_manage.BaseFromRzdIndexList
+	if len(rzdIndexList) > 0 {
+		rzdIndex = rzdIndexList[0]
+		// 查询指标数据
+		var condition string
+		var pars []interface{}
+		condition += ` and index_code = ?`
+		pars = append(pars, indexCode)
+
+		count, err := data_manage.GetBaseFormRzdDataByConditionCount(condition, pars)
+		if err != nil {
+			return nil, err
+		}
+		pagingItem := paging.GetPaging(currentIndex, pageSize, count)
+		if count <= 0 {
+			rzdIndex.Paging = pagingItem
+		} else {
+			condition += ` ORDER BY data_time desc`
+
+			condition += ` LIMIT ?, ?`
+			pars = append(pars, startSize, pageSize)
+
+			dataList, err := data_manage.GetBaseFormRzdDataByCondition(condition, pars)
+			if err != nil {
+				return nil, err
+			}
+
+			rzdIndex.Paging = pagingItem
+			rzdIndex.DataList = dataList
+		}
+
+		// 查询是否在指标库
+		edbInfo, err := data_manage.GetEdbInfoByEdbCode(utils.DATA_SOURCE_RZD, indexCode)
+		if err != nil && err.Error() != utils.ErrNoRow() {
+			return nil, err
+		}
+
+		if edbInfo != nil {
+			rzdIndex.EdbInfoId = edbInfo.EdbInfoId
+		}
+	}
+
+	return rzdIndex, nil
+}
+
+// GetRzdIndexList 获取指标列表
+func GetRzdIndexList(searchParams string) (rzdIndexInfoList []*data_manage.BaseFromRzdIndexList, err error) {
+
+	// 获取指标
+	var condition string
+	var pars []interface{}
+	if searchParams != "" {
+		condition += ` and index_code like ? or index_name like ?`
+		pars = append(pars, "%"+searchParams+"%", "%"+searchParams+"%")
+	}
+	rzdIndexList, err := data_manage.GetRzdIndex(condition, pars)
+	if err != nil {
+		return nil, err
+	}
+
+	return rzdIndexList, nil
+}

+ 11 - 0
utils/common.go

@@ -748,6 +748,17 @@ func TimeToStr(data time.Time, format string) string {
 	return data.Format(format)
 }
 
+func FormatDateString(format string) string {
+	// 解析源时间
+	t, err := time.Parse(FormatDateTime, format)
+	if err != nil {
+		return ""
+	}
+
+	// 格式化为目标时间格式
+	return t.Format(FormatDate)
+}
+
 // 字符串类型时间转周几
 func StrDateTimeToWeek(strTime string) string {
 	var WeekDayMap = map[string]string{

+ 1 - 0
utils/constants.go

@@ -186,6 +186,7 @@ const (
 	DATA_SOURCE_TRADE_ANALYSIS                       = 92       // 持仓分析
 	DATA_SOURCE_HISUGAR                              = 93       // 泛糖科技 -> 93
 	DATA_SOURCE_CALCULATE_STL                        = 98       // STL趋势分解 -> 98
+	DATA_SOURCE_RZD                                  = 97       // 睿姿得数据
 )
 
 // 数据刷新频率